09_Singleton mode

Description

定义:
保证一个类仅有一个实例,并提供一个全局访问点

类型:创建型

适用场景:
想确保任何情况下都绝对只有一个实例

优点:
在内存里只有一个实例,减少了内存开销
可以避免对资源的多重占用
设置全局访问点,严格控制访问

缺点:
没有接口,扩展困难

重点:
私有构造器
线程安全
延迟加载
序列化和反序列化安全
反射

1. Lazy man

1.1 Double check mechanism

package com.study.single_instance.java.lazy;

public class DoubleCheckSingleInstance {
    
    
    /**
     * 禁止重排序:volatile关键字保证所有线程都能看到共享内存的状态,保证了内存的可见性。
     * 用volatile修饰的共享变量在进行写操作的时候,当前处理器缓存行的数据写回到系统内存,
     * 同时使得其它CPU缓存了该内存地址的数据无效。
     * 当处理器发现缓存无效之后,就会在去系统内存中获取数据。(缓存一致性协议)
     */
    private volatile static DoubleCheckSingleInstance doubleCheckSingleInstance=null;
    private DoubleCheckSingleInstance(){
    
    }
    public static DoubleCheckSingleInstance getInstance(){
    
    
        if(doubleCheckSingleInstance==null){
    
    
            synchronized (DoubleCheckSingleInstance.class) {
    
    
                if(doubleCheckSingleInstance==null) {
    
    
                    /**
                     * doubleCheckSingleInstance = new DoubleCheckSingleInstance();分为三步
                     * 1.分配对象的内存空间
                     * 2.初始化对象
                     * 3.设置instance指向内存空间
                     * 2或3步可以重排序
                     */
                    doubleCheckSingleInstance = new DoubleCheckSingleInstance();
                }
            }
        }
        return doubleCheckSingleInstance;
    }
}

1.2 The way of static inner class

package com.study.single_instance.java.lazy;

public class StaticClassSingleInstance {
    
    
    private static StaticClassSingleInstance staticClassSingleInstance=null;
    private StaticClassSingleInstance(){
    
     }

    private static class InnerInstanceHolder{
    
    
        /**
         * 只有当有线程调用getInstance方法时,staticClassSingleInstance才会被初始化。
         * Class被加载之后以及被线程使用之前都是类的初始化阶段,在这个阶段
         * JVM会执行初始化,JVM会去获取一个锁。这个锁可以同步多个线程对一个
         * 类的初始化,这时候只有持有这个锁的线程才能看到类的初始化过程中的
         * 重排序。
         *
         */
        private  static StaticClassSingleInstance staticClassSingleInstance=new StaticClassSingleInstance();
    }


    public static StaticClassSingleInstance getInstance(){
    
    
        return InnerInstanceHolder.staticClassSingleInstance;
    }
}

2. Hungry Chinese

2.1 Member variable initialization

package com.study.single_instance.java.hungry;

import java.io.Serializable;

public class LazySingleInstance implements Serializable,Cloneable {
    
    
    private final static LazySingleInstance lazySingleInstance=new LazySingleInstance();
    private LazySingleInstance(){
    
    }
    public static LazySingleInstance getInstance(){
    
    
        return lazySingleInstance;
    }

    //用于反序列化调用,方法签名要与下列方法签名一致才可以,因为在反序列化的
    //过程中虚拟机会去检测当前内中是否存在该方法。
    public Object readResolve(){
    
    
        return lazySingleInstance;
    }
}

2.2 Member variable static code block initialization

package com.study.single_instance.java.hungry;

public class LazyStaticInitSingleInstance {
    
    
    private final static LazyStaticInitSingleInstance lazyStaticSingleInstance;
    static {
    
    
        lazyStaticSingleInstance = new LazyStaticInitSingleInstance();
    }
    private LazyStaticInitSingleInstance(){
    
    }
    public static LazyStaticInitSingleInstance getInstance(){
    
    
        return lazyStaticSingleInstance;
    }

}

Three, multi-threaded debugging method

Guess you like

Origin blog.csdn.net/Duckdan/article/details/109889116