java 知识点白鹿书单Java设计模式

7 种单例模式设计

2019-11-05  本文已影响0人  Tim在路上

饿汉式

// final 不允许被继承 
public final class Singleton {
    
    // 饿汉式,先new
    private static Singleton singleton = new Singleton();
    
    // 私有构造不允许外部 new
    private Singleton(){
        
    }
    
    public static Singleton getInstance(){
        return singleton;
    }
    
}

饿汉式的问题是 instance 在被 ClassLoader加载后很长时间才能在使用,如果类中的资源是重资源,那么就必须使用懒汉式

懒汉式

// final 不允许被继承
public final class Singleton {

    // 饿汉式,先new
    private static Singleton singleton = null;

    // 私有构造不允许外部 new
    private Singleton(){
        
    }

    public static Singleton getInstance(){
        if (singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
    
}

问题是多线程下不能保证实例的唯一性。

懒汉式+ 同步

// 但是 只允许一个 线程 访问这个方法 ,效率就会很低

// final 不允许被继承
public final class Singleton {

    // 饿汉式,先new
    private static Singleton singleton = null;

    // 私有构造不允许外部 new
    private Singleton(){

    }

    public static synchronized Singleton getInstance(){
        if (singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }

}

Double-check

//

// final 不允许被继承
public final class Singleton {

    // 饿汉式,先new
    // 不加 volatile 可能出现空指针异常 ,可能JVM指令的重排序
    private volatile static Singleton singleton = null;

    // 私有构造不允许外部 new
    private Singleton(){
    }
    // 双重校验,可以进入方法
    public static  Singleton getInstance(){
        if (singleton == null){
            synchronized(Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

Holder 实现静态的私有内部类

// final 不允许被继承
public final class Singleton {
    
    // 私有构造不允许外部 new
    private Singleton(){
         
    }

    private static class Holder{
        private static Singleton instance = new Singleton();
    }

    public static Singleton getInstance(){
        return Holder.instance;
    }
}

Singleton 类中,初始化过程中并不会创建 Singleton 的实例 ,只有当 Holder 类被主动引用的时候则会创建

枚举方式

枚举的方式不允许被继承,同时是线程安全的 ,只能被实例化一次

推荐使用枚举的方式

饿汉式

public enum  Singleton {

    INSTANCE;
    // 私有构造不允许外部 new
    private Singleton(){
        System.out.println("Instance will be init immediately");
    }
    //
    public static Singleton getInstance(){
        return INSTANCE;
    }
}

// 懒加载

把枚举作为内部类进行懒加载

public class Singleton {

    private Singleton(){

    }

    private enum EnumHolder{
        INSTANCE;
        private Singleton instance;
        
        EnumHolder(){
            this.instance = new Singleton();
        }
        
        private Singleton getInstance(){
            return instance;
        }
    }
    
    public static Singleton getInstance(){
        return EnumHolder.INSTANCE.getInstance();
    }
}
上一篇下一篇

猜你喜欢

热点阅读