进化的单例模式君

单例模式应该是涉及学习的较早的模式之一了,俗话说,麻雀虽小......呸呸呸,话又多了

先来个大纲,对于java而言,你也是单例只有两种。吓死你,回字的四种写法。

1  饿汉模式(加载类时比较慢,但获取对象时快)

2 懒汉模式(加载类时快,运行获取对象慢)

3 通过java加载类时先加载静态{static}资源的手段(歪门邪道)

4 通过枚举(奇巧淫技)

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

1   饿汉模式大概这样,不多说


public class SingletonHungry {

	private SingletonHungry() {
	}

	private static SingletonHungry instance = new SingletonHungry();

	public static SingletonHungry getSingleton() {
		return instance;
	}

}
---------------------------------------------------------

懒汉模式的初级样子

public class SingletonLazy {

	private SingletonLazy() {
	}

	private static SingletonLazy instance = null;

	public static SingletonLazy getSingleton() {
		
		if(instance ==null){
			instance =new SingletonLazy();
		}
		return instance;
	}

}

这种模式在单线程下是玩的很high的,但是多线程就扑街了。





所以,懒汉模式进化 --》 synchronized懒汉模式

public class SingletonLazy {

	private SingletonLazy() {
	}

	private static SingletonLazy instance = null;

	public static synchronized SingletonLazy getSingleton() {
		
		if(instance ==null){
			instance =new SingletonLazy();
		}
		return instance;
	}

}



多线程是安全,但是每次获得对象都需要走一次synchronized这个重量级锁,影响效率啊

懒汉模式进化 ---》》  双重判断懒汉模式

public class SingletonLazy {

	private SingletonLazy() {
	}

	private static SingletonLazy instance = null;

	public static  SingletonLazy getSingleton() {
		
		if(instance ==null){
			  synchronized(SingletonLazy.class){
				  if(instance==null){
					  instance =new SingletonLazy();
				  }
			  }
		}
		return instance;
	}

}




但是如果你运气足够好,这种模式下并发还是可能出问题。大概解释是,因为指令重排序的关系,比如三部曲


     (1)分配内存空间。

  (2)初始化对象。

  (3)将内存空间的地址赋值给对应的引用。

但是由于操作系统可以对指令进行重排序,所以上面的过程也可能会变成如下过程:

  (1)分配内存空间。

  (2)将内存空间的地址赋值给对应的引用。

  (3)初始化对象


最后懒汉模式究极进化 ,上volatile的懒汉模式

  

public class SingletonLazy {

	private SingletonLazy() {
	}

	private static volatile SingletonLazy instance = null;

	public static  SingletonLazy getSingleton() {
		
		if(instance ==null){
			  synchronized(SingletonLazy.class){
				  if(instance==null){
					  instance =new SingletonLazy();
				  }
			  }
		}
		return instance;
	}

}



虽然说这个是单例模式不能new出来,但是实际上能够通过反射给弄个新对象。

不过如果是枚举的单例就不能通过反射弄一个新的。暂时不讨论这个花式摸鱼。


总结:  单例模式,还是饿汉模式好用........














   

   

原文地址:https://www.cnblogs.com/fangyuandoit/p/13713865.html