Java单例模式

2021-04-14  本文已影响0人  arrow_zh

单例的5中方式

1、懒汉式

缺点:线程不安全

/**
     * 懒汉式
     * 缺点:线程不安全的
     */
    static class LazyClass {
        private static LazyClass lazyClass = null;
        private LazyClass (){}

        public static LazyClass getInstance(){
            if(lazyClass == null) {
                lazyClass = new LazyClass();
            }
            return lazyClass;
        }
    }

2、懒汉式变种(双重检查加锁)

/**
     * 懒汉式变种
     * 注意此处的变量必须加volatile修饰 如果不加volatile可能造成线程不安全
     * 主要原因是英文 doubleCheckClass = new DoubleCheckClass() 不是原子操作
     * 其中分为三步,第一步开辟内存空间,第二步初始化对象, 第三步赋值引用,其中在高并发场景下可能发生指重排
     * 双重检查加锁
     */
    static class DoubleCheckClass {
        private static volatile DoubleCheckClass doubleCheckClass = null;

        private DoubleCheckClass(){}

        public static DoubleCheckClass getInstance(){
            if(doubleCheckClass == null) {
                synchronized (DoubleCheckClass.class) {
                    doubleCheckClass = new DoubleCheckClass();
                }
            }
            return doubleCheckClass;
        }
    }

3、饿汉式

/**
 *饿汉式
*缺点:一上来就初始化空间,不是用也要占用内存空间
*/
static class HungryClass {
    private static HungryClasshungryClass= new HungryClass();

    private HungryClass(){}

    public static HungryClass getInstance(){
        returnhungryClass;
    }
}

4、静态内部类方式

/**
     * 静态内部类方式实现
     */
    static class InnerClass {
        private static class  InnerClassHolder {
            /**
             * 静态类初始化 JVM来保证线程安全
             */
            private static  InnerClass innerClass = new InnerClass();
        }

        private InnerClass(){}

        public static InnerClass getInstance(){
            return InnerClassHolder.innerClass;
        }
    }

5、枚举

/**
 *枚举方式实现单例
*/
static enum EnumClass {
instance;

}

破坏单例的三种方式

1、反射

解决方案:定义一个全局变量,当第二次创建时候就抛出异常

2、克隆

解决方案:重写clone方法,直接返回当前单例对象

3、序列化

解决防范:添加readResolve() 返回单例对象

/**
     * 破坏单例的几种方式
     * 1、反射
     * 2、克隆
     * 3、序列化
     *
     * 解决方法
     * 1、反射
     *    定义一个全局变量,当第二次创建的时候抛出异常
     * 2、克隆
     *   重写clone(),直接返回单例对象
     * 3、序列化
     *    添加readResolve(),返回Object对象
     */
    static class Singleton  implements Serializable,Cloneable{

        private static volatile boolean isCreate = false;//默认是第一次创建
        /**
         * 1.构造方法私有化,外部不能new
         */
        private Singleton() {
            if(isCreate) {
                throw new RuntimeException("已然被实例化一次,不能在实例化");
            }
            isCreate = true;
        }

        //2.本类内部创建对象实例
        private static  volatile  Singleton instance;

        //3.提供一个公有的静态方法,返回实例对象
        public static  Singleton getInstance() {
            if(instance == null) {
                synchronized (Singleton.class) {
                    if(instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return instance;
        }

        /**
         * 防止序列化破环
         * @return
         */
        private Object readResolve() {
            return instance;
        }

    }
上一篇下一篇

猜你喜欢

热点阅读