单例模式

来源:互联网 发布:淘宝类目销售比列 编辑:程序博客网 时间:2024/06/07 10:47

单例模式

作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。 –《JAVA与模式》

目前众所周知,单例模式主要有两种实现方式,一种是懒汉式,一种是饿汉式;其中懒汉式比较容易理解,但是作为饿汉式在实现的时可能有点麻烦。

  • 饿汉式

    饿汉式指的是在对象初始化的时候,那么就提供该对象的实例提供外部访问,无论外界是否真的需要该对象的实例。

    public class EagerSingleton {    private static final EagerSingleton eagerSingleton = new EagerSingleton();        /**私有化构造方法,不对外提供出去*/        private EagerSingleton () {    }    public static EagerSingleton getInstance() {        return eagerSingleton;    }}
  • 懒汉式

    懒汉式对比与饿汉式,他不会想饿汉式在初始化对象就实例化对象出来,与之不同的是在外部需要获取该对象的实例时,才初始化对象,这样做的好处就是在一定程度上节省的内存的消耗

    public class LazySingleton {    private static LazySingleton lazySingleton = null;    /**私有化构造方法,不对外暴露*/    private LazySingleton() {    }    /**     * 提供公共获取对象实例方法暴露出去     * 这里添加synchronized是为了在多线程环境下,保证依然提供单例出去;     * 比如说A,B两个线程同时进入getInstance方法中,两个线程在判断lazySingleton是否为null时,都是true,那么就会提供两个不通过的实例化对象出去     * @return     */    public static synchronized LazySingleton getInstance() {        if (lazySingleton == null) {            lazySingleton = new LazySingleton();            return lazySingleton;        }        return lazySingleton;    }}

    但是关于上面懒汉式的实现有一个瑕疵,就是每一次在去获取LazySingleton实例化是都需要上一个线程在获取结束之后,这样有一定的性能的问题,当然我们可以对这里的代码进行优化。

    public class DoubleLockLazySingleton {    /**     * 这里使用volatile关键字,是为了保证doubleLockLazySingleton在多线程环境下保持一致性,     * 所谓的一致性指的是N个线程在同时对doubleLockLazySingleton进行处理时,其中任意线程在对     * doubleLockLazySingleton已经进行了改变,那么其他线程可以马上获取到改变之后的doubleLockLazySingleton     */    private static volatile DoubleLockLazySingleton doubleLockLazySingleton = null;    private DoubleLockLazySingleton() {    }    public static DoubleLockLazySingleton getInstance() {        // 初次判断doubleLockLazySingleton是否为空,        if (doubleLockLazySingleton == null) {            synchronized (DoubleLockLazySingleton.class) {                // 再次判断是之前的判断是处于线程不安全的,所以需要再次判断,防止发生并发问题                if (doubleLockLazySingleton == null) {                    doubleLockLazySingleton = new DoubleLockLazySingleton();                    return doubleLockLazySingleton;                }            }        }        return doubleLockLazySingleton;    }}

    这里笔者提供两种其他关于单例懒汉式的实现

    • 内部类实现
    public class InnerClassLazySingleton {    private InnerClassLazySingleton() {    }    private static class InnerClassLazySingletonHolder {        private static InnerClassLazySingleton InnerClassLazySingleton = new InnerClassLazySingleton();    }    public static InnerClassLazySingleton getInstance() {        /**         * 这里之所以使用内部类的实现方式,是因为在JVM在加载类中的静态字段(或者静态代码块)是保证同步的,         * 也就是说在N个线程在同步访问getInstance方法时,这里是去加载了InnerClassLazySingleton         * 中的内部静态类InnerClassLazySingletonHolder,而加载内部静态类时又是同步的,那么就代表着         * 这里只有一个线程加载了InnerClassLazySingletonHolder,而且作为一个静态内部类而言,他在整个         * 系统中只会加载一次,他的生命周期是伴随着InnerClassLazySingleton而存在的         */        return InnerClassLazySingletonHolder.InnerClassLazySingleton;    }}
    • 枚举单例实现
    public enum EnumSingleton {    SINGLETON;    public void doSomething() {        // TODO    }}

    以上所有内容转自《JAVA与模式》之单例模式

0 0