单例模式

单例模式

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值