单例模式

来源:互联网 发布:六个字的网络流行语 编辑:程序博客网 时间:2024/06/17 07:48

保证一个类有且只有一个实例,并提供一个访问该实例的全局访问点。要提供一个全局访问点,最常用的办法便是使用类的静态方法,静态方法只能从类而不是从实例中调用。
当一个对象在系统中独一无二,只能有一个的时候,比如一个打印设备,一个进程管理器等等,在这上面,觉得有些类似于多线程锁的概念(所以后面会用到线程同步synchronized)

单例模式比较普遍的提到了3种形式(懒汉式,饿汉式,单例注册表)

//懒汉,线程不安全public class Singleton {      private static Singleton singleton;//创建一个静态变量来保存类的实例      private Singleton(){}//将构造函数声明为私有,以防止外类访问,导致多次实例化      public static Singleton getInstance(){//提供一个全局访问点,返回该类的唯一实例          if(singleton==null){//检查实例是否已经存在,保证唯一性              singleton=new Singleton();          }          return singleton;      }  }

致命的是在多线程不能正常工作

//懒汉,线程安全public class Singleton {      private static Singleton instance;      private Singleton (){}      public static synchronized Singleton getInstance() {      if (instance == null) {          instance = new Singleton();      }      return instance;      }  }  

这种写法能够在多线程中很好的工作,而且看起来它也具备很好的lazy loading,但是,遗憾的是,效率很低,99%情况下不需要同步。

//饿汉public class Singleton {      private static Singleton instance = new Singleton();  //提前实例化    private Singleton (){}      public static Singleton getInstance() {      return instance;      }  }  

这种方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到lazy loading的效果。

//双重锁(double-checked locking)public class Singleton {      private volatile static Singleton singleton;      private Singleton (){}      public static Singleton getSingleton() {      if (singleton == null) {          synchronized (Singleton.class) {          if (singleton == null) {              singleton = new Singleton();          }          }      }      return singleton;      }  }  

在不同的classloader或者虚拟机JVM下,可能会造成结果的不可预知,所以加了2重锁,volatile关键字,也是为了这个目的,声明为volatile的变量就是可能产生不可预知结果的,volatile保证变量总是从内存中拿去(好像是这样),在JDK1.5之后,双重检查锁定才能够正常达到单例效果。

单例模式的七种写法:http://cantellow.iteye.com/blog/838473

原创粉丝点击