1.单例-懒汉式

1.线程不安全
2.同步方法单例

3.双重检测
public class LazyDoubleCheckSingleton {
    private static volatile LazyDoubleCheckSingleton instance = null;

    private LazyDoubleCheckSingleton(){}



    public static LazyDoubleCheckSingleton newInstance(){
        if(null == instance){
            synchronized (LazyDoubleCheckSingleton.class){
                if(null == instance){
                    instance = new LazyDoubleCheckSingleton();
                }
            }
        }
        return instance;
    }
}


4.静态内部类
/**
 * 静态内部类,
 * 第一次加载LazySingleton2类时并不会初始化instance,只
 * 有第一次调用getInstance方法时虚拟机加载SingletonHolder 并初始化instance ,
 * 这样不仅能确保线程安全也能保证Singleton类的唯一性,
 * 所以推荐使用静态内部类单例模式。
 * @program: gof23
 * @link: 55864455@qq.com
 * @author: Mr.Xxm
 * @create: 2020-02-08 22:18
 **/
public class LazyInnerClassSingleton {

    private LazyInnerClassSingleton(){
        if(null != SingletonHolder.instance){
            throw new RuntimeException("不允许创建多个LazyInnerClassSingleton实例");
        }
    }

    public static LazyInnerClassSingleton newInstance(){
        return SingletonHolder.instance;
    }

    private static class SingletonHolder{
       private static final LazyInnerClassSingleton instance = new LazyInnerClassSingleton();
    }
}

温馨提示:
  1)  以上方式都能被反射获取,如果静止反射的话,需要再无参构造抛出异常,来禁止破坏单例

   2) 被反序列化操作

反序列化之后,依然破坏了单例,这时候如果要保证单例  需要以下操作
    /**
     * 重写readResolve方法,只不过是覆盖了反序列化出来的对象
     * 还是创建了两次,发生在JVM层面,相对来说比较安全
     * 之前反序列化出来的对象会被GC回收
     * @return
     * @throws ObjectStreamException
     */
    private Object readResolve()  throws ObjectStreamException {
        return INSTANCE;
    }
ObjectInputStream.readOrdinaryObject(boolean unshared)   方法2032行





5.枚举式单例
/**
 * @program: gof23
 * @link: 55864455@qq.com
 * @author: Mr.Xxm
 * @create: 2020-02-09 00:48
 **/
public enum EnumSingleton {

    INSTANCE;

    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public static EnumSingleton newInstance(){
        return INSTANCE;
    }
}
1) 反序列化分析
    

2) 反射分析
不能反射式地创建枚举对象,这是JDK为枚举天然保驾护航,保障其单例性




6.容器式单例
/**
 * @program: gof23
 * @link: 55864455@qq.com
 * @author: Mr.Xxm
 * @create: 2020-02-09 00:37
 **/
public class ContainerSingleton {
    private static Map<String, Object> ioc = new ConcurrentHashMap<>();

    private ContainerSingleton() {
    };

    public static Object getBean(String className) {
        if (!ioc.containsKey(className)) {
            synchronized (ioc) {
                if (!ioc.containsKey(className)) {
                    Object obj = null;
                    try {
                        obj = Class.forName(className).newInstance();
                        ioc.put(className, obj);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return ioc.get(className);
    }
}





posted @ 2020-02-15 16:21  码里有毒  阅读(124)  评论(0)    收藏  举报