参考网站: 

1.

2.

2.

主要内容:

什么是单例模式?单例模式是一种设计模式,其设计的思路是:一个特殊的类,它只有一个实例,而且这个类提供了访问这个类的方法;

单例模式从实现上可分为饿汉式懒汉式:

饿汉式:

//单例模式————"饿汉式"的代码规范class SingleHungry{ //此处有关键字final修饰aSingleInstanceObjRef,则表明次对象不可修改, //虽然不要final也可以实现效果,但这样做更加规范。 private static final SingleHungry aSingleInstanceObjRef = new Single(); private SingleHungry() {} public SingleHungry getSingle() {  return aSingleInstanceObjRef; }}

优点:线程安全;

缺点:在未调用之前已经进行实例化,占用了相应的系统资源。

懒汉式:

//单例模式————"懒汉式"的代码//下列代码是“线程不安全”的写法。class SingleLanHan{ //此处不能有关键字final,否则aSingleInstanceObjRef引用就无法被复制了, //因为它被定为以为一个常量null private static SingleLanHan aSingleInstanceObjRef = null; private SingleLanHan() {} public SingleLanHan getSingleLanHan(){  if(aSingleInstanceObjRef == null) {  // A   aSingleInstanceObjRef = new SingleLanHan();  // B  }  return aSingleInstanceObjRef;   }}

优点:在调用时才进行实例化;

缺点:线程不安全。原因:线程1和线程同时进入了A,线程1抢占了资源,执行了B,后来线程B也获得了资源,执行了B,这时候该类就被实例化两次,造成了线程不安全。

解决方案一(加锁):

//单例模式————"懒汉式"的代码//下列代码是“线程不安全”的写法。class SingleLanHan{ //此处不能有关键字final,否则aSingleInstanceObjRef引用就无法被复制了, //因为它被定为以为一个常量null private static SingleLanHan aSingleInstanceObjRef = null; private SingleLanHan() {} public synchronized SingleLanHan getSingleLanHan(){  if(aSingleInstanceObjRef == null) {  //  A   aSingleInstanceObjRef = new SingleLanHan();  }  return aSingleInstanceObjRef;   }}

这个解决方案使用了synchronized关键字对来防止不同线程同时进入A处,由于单例模式只实例化一次,在往后的获取改实例的时候,都需要进行判断是否有其他的线程在占用着锁,效率低。

解决方法二(双重锁):

//单例模式————"懒汉式"的代码规范class SingleLanHan{ //此处不能有关键字final,否则aSingleInstanceObjRef引用就无法被复制了, //因为它被定为以为一个常量null private static SingleLanHan aSingleInstanceObjRef = null; private SingleLanHan() {} public SingleLanHan getSingleLanHan(){      if(aSingleInstanceObjRef == null) {     //A   synchronized(SingleLanHan.class) {        if(aSingleInstanceObjRef == null) {     aSingleInstanceObjRef = new SingleLanHan();     return aSingleInstanceObjRef;    }   }  }else {   return aSingleInstanceObjRef;  } }}

这个解决方案在synchronized关键字之前加上了一条if语句(A处),在未实例化之前,synchronized的锁依然起作用,同时,在synchronized内部也需要一条判断语句,防止线程陆续进入synchronized块后重复实例化;而实例化后,它(A处)的作用就是隔离了synchronized块的操作。效率比方面方案一高。

解决方案三(内部类):

public class Singleton {	static class SingletonHolder {		static Singleton instance = new Singleton();	}	public static Singleton getInstance() {		return SingletonHolder.instance;	}}

JVM内部的机制能够保证当一个类被加载的时候,这个类的加载过程是线程互斥的。这样当我们第一次调用getInstance的时候,JVM能够帮我们保证instance只被创建一次,并且会保证把赋值给instance的内存初始化完毕,同时,instance是在第一次加载SingletonContainer类时被创建的,而SingletonContainer类则在调用getInstance方法的时候才会被加载,因此也实现了lazy加载。

小小的单例模式还是有着这么大的学问,先记录下来,以备回顾之用。