单例模式的几种实现

来源:互联网 发布:免费叫卖录音软件 编辑:程序博客网 时间:2024/06/07 11:48

单例模式的几种实现

在开发中,我们总是会遇到使用单例模式的情况,今天就来总结一下几种实现单例模式的方法。
1.单例模式(懒汉式)的最佳写法(特别说到这个问题,是因为网上很多这样的代码)。

public class Singleton {    private  static Singleton singleton;    public Singleton() {    }    public static Singleton getInstance() {        if (singleton == null) {            singleton = new Singleton();        }        return singleton;    }}

这种写法只能在单线程下使用。如果是多线程,可能发生一个线程通过并进入了 if (singleton == null) 判断语句块,但还未来得及创建新的实例时,另一个线程也通过了这个判断语句,两个线程最终都进行了创建,导致多个实例的产生。所以在多线程环境下必须摒弃此方式。
这种写法线程不安全。
2.加入同步锁。

    public class Singleton {    private  static Singleton singleton;    public Singleton() {    }    public static synchronized Singleton getInstance() {        if (singleton == null) {            singleton = new Singleton();        }        return singleton;    }}

通过为 getInstence() 方法增加 synchronized 关键字,迫使每个线程在进入这个方法前,要先等候别的线程离开该方法,即不会有两个线程可以同时进入此方法执行 new Singleton(),从而保证了单例的有效。但它的致命缺陷是效率太低了,每个线程每次执行 getInstance() 方法获取类的实例时,都会进行同步。而事实上实例创建完成后,同步就变为不必要的开销了,这样做在高并发下必然会拖垮性能。所以此方法虽然可行但也不推荐。
网上这样的代码更多,可以很好的工作,但是缺点是效率低。
3.实际上,早在JDK1.5就引入volatile关键字,所以又有了一种更好的双重校验锁写法。

public class Singleton {    private volatile static Singleton singleton;    public Singleton() {    }    public static  Singleton getInstance() {        if (singleton == null) {            synchronized (Singleton.class) {                if (singleton == null) {                    singleton = new Singleton();                }            }        }        return singleton;    }}

DCL体现在进行了两次 if (singleton == null) 的检查,这样既同步代码块保证了线程安全,同时实例化的代码也只会执行一次,实例化后同步操作不会再被执行,从而效率提升很多。
双重检查锁定(DCL)方式也是延迟加载的,它唯一的问题是,由于 Java 编译器允许处理器乱序执行,在 JDK 版本小于 1.5 时会有 DCL 失效的问题(原因解释详见附录 2)。当然,现在大家使用的 JDK 普遍都已超过 1.4,只要在定义单例时加上 1.5 及以上版本具体化了的 volatile 关键字,即可保证执行的顺序,从而使单例起效。所以 DCL 方式是推荐的一种方式。
Android 中鼎鼎大名的 Universal Image Loader 和 EventBus 都是采用了这种方式的单例
这才是最佳写法!!!

不是说第二种写法有问题,或者在Android中一定要用第三种写法,只是告诉大家一种更好的写法。

2 0
原创粉丝点击