singleton-单例设计模式

八种单例设计模式

  • 饿汉式-两种写法
  • 懒汉式 lazy loading (第四种写法完美)
  • 静态内部类方法(完美)
  • 枚举类实现单例 (完美中的完美,但是一般用上面几种)

饿汉式

两种写法在效果上没有什么区别。
第一种写法

/**
 * 饿汉式
 * 在类加载到内存时就实例化一个对象,jvm保证线程安全。
 * 简单实用,推荐使用。
 * 唯一缺点,就算你不用它,他也会加载,浪费内存。
 */
public class Mgr01 {
    private static final Mgr01 INSTANCE = new Mgr01();

    private Mgr01(){}

    public static Mgr01 getInstance(){
        return INSTANCE;
    }
}

第二种写法

public class Mgr02 {
    private static final Mgr02 INSTANCE;

    /**
     * 实例化代码写在静态代码块中
     */
    static {
        INSTANCE = new Mgr02();
    }
    private Mgr02(){}
    public static Mgr02 getInstance(){
        return INSTANCE;
    }
}

懒汉式

在初次使用时进行实例化,之后不再进行实例化。
第一种写法(有线程安全问题),如果多个线程同时来获取示例可能引发线程安全问题,导致实例被创建多次。

public class Mgr03 {
    private static Mgr03 INSTANCE;

    private Mgr03(){}

    public static Mgr03 getINSTANCE() {
        if (INSTANCE == null){
            INSTANCE = new Mgr03();
        }
        return INSTANCE;
    }
}

第二种写法,加synchronized 保证线程安全。问题:性能下降。

public class Mgr04 {
    private static Mgr04 INSTANCE;
    private Mgr04(){}
    /*
     * 此处增加 synchronized 来保证只有一个示例对象。性能会下降。
     */
    public static synchronized Mgr04 getINSTANCE() {
        if (INSTANCE == null){
            INSTANCE = new Mgr04();
        }
        return INSTANCE;
    }
}

第三种写法,依然有问题,同样是线程安全问题。

public class Mgr05 {
    private static Mgr05 INSTANCE;
    private Mgr05(){}
    public static Mgr05 getINSTANCE() {
        if (INSTANCE == null){
            // 此处堆积线程发生多次实例化
            synchronized (Mgr05.class){
                INSTANCE = new Mgr05();
            }
        }
        return INSTANCE;
    }
}

第四种写法,完美写法。

public class Mgr06 {
    // volatile 用来防止极小概率发生的指令重排序导致的错误。追求完美要加
    private static volatile Mgr06 INSTANCE;
    private Mgr06(){}
    public static Mgr06 getINSTANCE() {
        if (INSTANCE == null){ // 第一次验证
            synchronized (Mgr06.class){
                if (INSTANCE == null){// 第二次验证
                    INSTANCE = new Mgr06();
                }
            }
        }
        return INSTANCE;
    }
}

静态内部类方式

这种方式完美。由静态内部类来实现懒加载,和 jvm 实现线程安全。

public class Mgr07 {
    private Mgr07(){}

    private static class Mgr07Holder{
        private static final Mgr07 INSTANCE = new Mgr07();
    }

    private Mgr07 getInstance(){
        return Mgr07Holder.INSTANCE;
    }
}

枚举类实现

也是完美写法。但用的比较少。

public enum Mgr08 {
    INSTENCE;
    public void m(){
        // 这里是单例的方法
        System.out.println("业务方法");
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容