Singleton单例模式

89 阅读2分钟

01.概念

创建型模式,提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意:

  • 1、单例类只能有一个实例。
  • 2、单例类必须自己创建自己的唯一实例。
  • 3、单例类必须给所有其他对象提供这一实例。

02.重点

将构造方法设为私有,通过方法提供实例。

2.1 饿汉式

类加载到内存后,就实例化一个单例,JVM保证线程安全。
简单实用,推荐。
唯一缺点:不管用到与否,类加载时都会完成实例化。

public class Mgr01 {
    private static final Mgr01 INSTANCE = new Mgr01();

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

2.2 懒汉式

使用的时候才初始化,但相应的带来了线程不安全的问题

public class Mgr02 {
    private static Mgr02 INSTANCE;

    private Mgr02() {
    }

    public static Mgr02 getInstance() {
        if (INSTANCE != null) {
            INSTANCE = new Mgr02();
        }
        return INSTANCE;
    }
}

为什么说线程不安全呢,当两个线程同时判断if (INSTANCE != null)且进入if内部,则会有两个Mgr02 new出来
那么线程不安全如何解决呢
我们尝试加锁

public class Mgr03 {
    private static Mgr03 INSTANCE;

    private Mgr03() {
    }

    public static synchronized Mgr03 getInstance() {
        if (INSTANCE != null) {
            INSTANCE = new Mgr03();
        }
        return INSTANCE;
    }
}

这样每次在读取时都要进行加锁的操作,效率降低了
此时出现了双重检查单例写法,将锁加给属性

public class Mgr04 {
    private static Mgr04 INSTANCE;

    private Mgr04() {
    }

    public static Mgr04 getInstance() {
        if (INSTANCE != null) {
            synchronized (Mgr04.class){
                if (INSTANCE != null) {
                    INSTANCE = new Mgr04();
                }
            }
        }
        return INSTANCE;
    }
}

较为完美的方式, 静态内部类方式

public class Mgr05 {
    private Mgr05() {
    }

    private static class Mgr05Holder {
        private final static Mgr05 INSTANCE = new Mgr05();
    }

    public static Mgr05 getInstance() {
        return Mgr05Holder.INSTANCE;
    }
}

枚举

public enum Mgr06 {
    INSTANCE;
}