专栏首页大大的微笑设计模式之单例模式深究

设计模式之单例模式深究

为什么使用单例模式?         我认为是由于某些对象的创建比较耗时,对内存的消耗又比较大回收成本过高,这时候如果允许 不断的创建对象代价势必太高,如果使用单例让内存中始终保持一个对象那么显然更划算

反例:

    ①. 同时执行1000个线程测试

public class Singleton3 {
	private static  Singleton3 INSTANCE;
	private Singleton3(){}
	public static Singleton3 getInstance(){
			if(INSTANCE == null){
				newInstance();
			}
		
		return INSTANCE;
	}
	private static void newInstance(){
		INSTANCE = new Singleton3();
	}


//test

public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
		final CyclicBarrier cb = new CyclicBarrier(1000);
		for(int i = 0; i <1000;i++){
			Thread t = new Thread(new Runnable() {
				
				@Override
				public void run() {
					try {
						cb.await();
                    } catch (Exception e) {
	                    e.printStackTrace();
                    }
					System.out.println(Singleton3.getInstance().hashCode());
				}
			});
			t.start();
		}
	}

 测试结果通过notepad++计数发现有几个不一致的发现有不一致的hashcode

11009893 --不一致
31038155
31038155
31038155
31038155
31038155
31038155
31038155
31038155
31038155
31038155
31038155
31038155
26417394  --不一致
31038155
31038155
31038155
...
省略

②.加锁的方式:

public static Singleton3 getInstance(){
		if (INSTANCE == null) {
			try {
				// 模拟一个耗时操作
	            Thread.sleep(3000);
	        } catch (InterruptedException e) {
	            // TODO Auto-generated catch block
	            e.printStackTrace();
	        }
			synchronized (Singleton3.class) {
				newInstance();
			}
		}
		return INSTANCE;
	}


//结果显而易见

18000767
10320474
9913454
2027657
10262576
15487566
15487566
28392674
15487566
6268557
6268557
25920236
....略

③.双重检查加锁(即做两次判断):这种方式虽然可行,但是使用锁毕竟会加重程序不建议使用

if (INSTANCE == null) {
			try {
				// 模拟一个耗时操作
	            Thread.sleep(3000);
	        } catch (InterruptedException e) {
	            // TODO Auto-generated catch block
	            e.printStackTrace();
	        }
			synchronized (Singleton3.class) {
				newInstance();
			}
		}
		return INSTANCE;
	}
	private static void newInstance(){
		if(INSTANCE == null){
			INSTANCE = new Singleton3();
		}
	}

------------------------------------------

使用如下几种方式:

①.静态块的方式:只会第一次创建对象的方式进来

private static  final Singleton2 INSTANCE;
	static{
		System.out.println("static.");
		INSTANCE = new Singleton2();
	}
	private Singleton2(){}
	public static Singleton2 getInstance(){
		return INSTANCE;
	}

②.类似于①

private static  final Singleton INSTANCE = new Singleton();
	private Singleton(){
		System.out.println("construct.");
	}
	public static Singleton getInstance(){
		return INSTANCE;
	}

③.枚举的方式(必须是单元素):

public enum Singleton4 {
	INSTANCE;
	public int get(){
		try {
			// 模拟耗时
	        Thread.sleep(1000);
        } catch (InterruptedException e) {
	        e.printStackTrace();
        }
		return Singleton4.class.hashCode();
	}
}

④.静态内部类:略

------------------------------------

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ArrayList底层实现

    package java.util; public class ArrayList<E> extends AbstractList<E> im...

    用户1215919
  • 设计模式之装饰模式

    其中一个配料类代码: public class Fruit extends AbstractDrinkDecorator { public Fruit(Dri...

    用户1215919
  • 观察者模式详解

    观察者模式是众多软件设计模式中的一种,又称发布订阅模式.被观察的对象发生了变化,观察者对象们可以第一时间收到通知, 并作出相应的处理,例如作为一家餐馆的会员...

    用户1215919
  • 实战:详解猫眼电影小程序开发过程

    作者:辉仔,Android开发工程师,目前主要涉及移动端APP的开发,Github地址:https://github.com/hundredays。 责编:陈...

    智能算法
  • 在 Asp.Net Core WebAPI 中防御跨站请求伪造攻击

    跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常...

    beginor
  • java基础第五篇封装与面向对象

    public static void main(String[] args) {

    海仔
  • java基础第四篇之面向对象

    形参:一般把 不确定的量或者变化的量定义在形参位置//圆的的半径,长方形的长和宽,传递的数组也是不确定的

    海仔
  • 科技驯化了人类

    人类在狩猎的游牧时代以及进入到的农耕时代都是贴近大自然依靠大自然的传统生活方式,基本根据季节变化而生活,干一天休两天都属于正常,甚至一个漫长的冬季都在等待春天的...

    机器思维研究院
  • ELF文件格式的详解

    ELF的英文全称是The Executable and Linking Format,最初是由UNIX系统实验室开发、发布的ABI(Application Bi...

    bigmagic
  • 你的物联网需要SD-WAN的3个原因

    3-Reasons-Why-Your-IoT-Initiatives-Need-SD-WAN-1-1920x1180-1.jpg

    用户4122690

扫码关注云+社区

领取腾讯云代金券