设计模式之单例模式

单例模式

针对某一个特别大的资源或者配置文件之类的,我们希望在一个应用中全局只需要一个对象就可以了,不然会造成系统资源的额外浪费,单例模式正是适合这种模式的。
一般常见的创建方式分为懒汉式和饿汉式。

懒汉式

懒汉式,从懒字出发,就是不到使用时,不会去动它,具体使用时调用获取对象方法时才具体创建对象。
这种方式有其有点,在使用的时候才进行初始化,可以节约系统资源,加快应用的启动速度等等,都是有好处的。

/**
 * 非线程安全版本
 * @author hexin
 * @version 1.0 2018/12/17
 */
public class LazySingleton {
    private static LazySingleton instance = null;
    /**
     * 构造函数置为私有,不希望外部调用该方法
     */
    private LazySingleton() {}
    /**
     * 获取单例对象,具体使用时才初始化对象,非线程安全的
     */
    public static LazySingleton getInstance() {
        if (instance == null)
            instance = new LazySingleton();
        return instance;
    }
}

下面是线程安全版本,使用了双重校验。

/**
 * 线程安全版本
 * 注意需要jdk1.5以后才行,之前版本的volatile无法保证该特点
 * @author hexin
 * @version 1.0 2018/12/17
 */
public class MultiThreadSafeLazySingleton {
    //使用volatile保证对象不会缓存在cpu cache中。
    private volatile static MultiThreadSafeLazySingleton instance = null;
    private MultiThreadSafeLazySingleton(){}

    /**
     * 此单例方法是线程安全的,相对于直接在方法上面使用synchronized关键字,性能好不少,
     * 不会限制为单次只有一个线程能够获取对象。
     * 是否初始化对象采用了双重校验,保证初始化只有一个对象。
     */
    public static MultiThreadSafeLazySingleton getInstance(){
        if (instance == null) {
            synchronized (MultiThreadSafeLazySingleton.class) {
                if (instance == null)
                    instance = new MultiThreadSafeLazySingleton();
            }
        }
        return instance;
    }
}
静态内部类

相对于使用双重校验的那种线程安全实现方式,还有一种更加巧妙的实现线程安全的方式——静态内部类
利用了java虚拟机的特点,类加载是线程安全的,而且静态内部类相对于其外部类来说是独立的,加载外部类不会立即加载静态内部类,利用这些特点,懒汉式的另一种实现方式如下:

/**
 * 使用静态内部类方式实现线程安全的延迟初始化单例对象
 * @author hexin
 * @version 1.0 2018/12/17
 */
public class StaticInnerLazySingleton {
    private StaticInnerLazySingleton(){}
    //保存单例的静态内部类
    private static class SingletonHolder {
        static StaticInnerLazySingleton instance = new StaticInnerLazySingleton();
    }
    public static StaticInnerLazySingleton getInstance() {
        return SingletonHolder.instance;
    }
}

饿汉式

正如其名所知,饥饿使得对象是载入该类时即会进行对象的初始化,和懒汉式是对象的。
饿汉式相对于懒汉式,简单,不需要考虑延迟初始化需要的各种处理,但是如果资源比较大的话,占用资源比较多,使应用启动速度减慢等等。

/**
 * 饿汉式,立即初始化单例对象,特点是简单,不需要考虑并发造成的问题。
 * @author hexin
 * @version 1.0 2018/12/17
 */
public class InstantSingleton {
    //立即初始化
    private final static InstantSingleton instance = new InstantSingleton();
    private InstantSingleton(){}
    public static InstantSingleton getInstance() {
        return instance;
    }
}

其他方式

  • 枚举类 枚举其实就是很好的单例例子,其每个枚举对象就是一个个的静态实例。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章