您的位置:首页 > 其它

单例模式

2015-08-25 22:22 302 查看
饿汉式(常用)

public class EagerSingleton {

    private static EagerSingleton instance = new EagerSingleton();

    /**

     * 私有默认构造子

     */

    private EagerSingleton(){}

    /**

     * 静态工厂方法

     */

    public static EagerSingleton getInstance(){

        return instance;

    }

}

懒汉式

public class LazySingleton {

    private static LazySingleton instance = null;

    /**

     * 私有默认构造子

     */

    private LazySingleton(){}

    /**

     * 静态工厂方法

     */

    public static synchronized LazySingleton getInstance(){

        if(instance == null){

            instance = new LazySingleton();

        }

        return instance;

    }

}

简单总结一下这样的写法:
提供一个全局静态的
getIns
方法,使得易于使用.
延迟Singleton的实例化,节省资源(所谓的懒汉式).
缺点是线程不安全.当多个线程同时进入
if (null ==
ins) {}
的时候就会创建多个实例.

饿汉式与之前提到的懒汉式不同,它在我们调用getIns之前就实例化了(在类加载的时候就实例化了),所以不是一个懒加载,这样就有几个缺点:
延长了类加载时间
如果没用到这个类,就浪费了资源(加载了但是没用它)
不能传递参数(很显然适用的场景会减少)


性能进阶

接下去介绍一种更优秀的,线程安全的单例写法---双重检查锁模式(double check locking pattern)

public class DoubleCheck {

private volatile static DoubleCheck ins;
private DoubleCheck() {}
public static DoubleCheck getIns() {
if (null==ins){ //检查
synchronized (DoubleCheck.class){
if (null == ins) { //又检查一次
ins = new DoubleCheck();
}
}
}
return ins;
}
}


注意这里的ins用了
volatile
关键字来修饰,为什么呢?

因为执行
ins = new DoubleCheck()
做了很多事情:
给ins分配内存
调用构造函数来初始化成员变量(可能会很久)
将ins对象指向分配的内存空间(执行完这步 ins才不为null)


静态内部类

静态内部类原理同上,另外虽然它看上去有点恶汉式,但是与之前的恶汉有点不同,它在类
Singleton
加载完毕后并没有实例化,而是当调用
getIns
去加载Holder的时候才会实例化,静态内部类的方式把实例化延迟到了内部类的加载中去了!所以它比饿汉式更优秀!(偷偷告诉你Effective
Java中也推荐这个方式)

例子:
public class Singleton {

private static class Holder{
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getIns(){
return Holder.INSTANCE;
}
}

推荐双重检查锁和静态内部类
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: