美文网首页
Singleton单例模式

Singleton单例模式

作者: silence_J | 来源:发表于2020-04-08 16:00 被阅读0次

应用场景

只需要一个实例

  • 如各种Mgr (manager管理类)
  • 如各种Factory

饿汉式

  • 类加载到内存后,就实例化一个单例,JVM保证线程安全
  • 简单实用,推荐使用
  • 缺点:不管是否用到,类装载时就完成实例化
/**
 *饿汉式:
 *
 * 类加载到内存后,就实例化一个单例,JVM保证线程安全
 * 简单实用,推荐使用
 * 缺点:不管是否用到,类装载时就完成实例化
 */
public class Mgr01 {

    private static final Mgr01 INSTANCE = new Mgr01();

    // 构造方法私有化
    private Mgr01() {};

    // 暴露给外部调用,返回同一个对象,保证单例
    public static Mgr01 getInstance() {
        return INSTANCE;
    }

    // 其它方法
    public void m(){};

}

懒汉式

写法1

优点:按需初始化
缺点:多线程时可能会创建多个实例

/**
 * lazy loading
 * 也称懒汉式
 * 虽然达到了按需初始化的目的,但多线程时会有一些问题
 */
public class Mgr02 {

    private static Mgr02 INSTANCE;

    // 构造方法私有化
    private Mgr02() {};

    // 该方法被调用时才创建实例
    public static Mgr02 getInstance() {
        // 此时若正好有多个线程进入判断,那么会new出多个对象
        if ( INSTANCE == null) {   
            INSTANCE = new Mgr02();
        }
        return INSTANCE;
    }

    // 其它方法
    public void m(){};

}

写法2

  • 加锁改进后解决多线程问题,但效率降低
/**
 * 懒汉式改进
 *
 * 可以通过synchronized解决多线程问题,但也带来效率下降
 */
public class Mgr03 {

    private static volatile Mgr03 INSTANCE;

    // 构造方法私有化
    private Mgr03() {};

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

    // 其它方法
    public void m(){};

}

写法3

  • 若想再进一步提高效率:判空后再加锁,双重检查锁(double-checked locking)
public class Mgr04 {

    private static volatile Mgr04 INSTANCE;

    // 构造方法私有化
    private Mgr04() {};

    // 该方法被调用时才创建实例
    public static Mgr04 getInstance() {
        if ( INSTANCE == null) {
            // 双重检查   如果是单次检查,仍有可能有多个线程进入if判断
            synchronized (Mgr04.class) {
                if ( INSTANCE == null ) {
                    INSTANCE = new Mgr04();
                }
            }
        }
        return INSTANCE;
    }

    // 其它方法
    public void m(){};

}

写法4

  • 静态内部类方式。懒加载,JVM保证线程安全。
    Mgr05类被加载时,内部类Mgr05Holder不会被加载,当getInstance()方法被调用时Mgr05Holder才会被加载,从而实现了懒加载
/**
 * 静态内部类方式
 * JVM保证单例
 * 加载外部类时不会加载内部类,这样可以实现懒加载
 */
public class Mgr05 {

    // 构造方法私有化
    private Mgr05() {};
    // 静态内部类
    private static class Mgr05Holder {
        private static final Mgr05 INSTANCE = new Mgr05();
    }

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

    // 其它方法
    public void m(){};

}

写法5

  • 枚举单例,语法上最完美
/**
 * 不仅可以解决线程同步,还可以防止反序列化
 */
public enum Mgr06 {

    INSTANCE;

    // 其它方法
    public void m(){};

}

相关文章

网友评论

      本文标题:Singleton单例模式

      本文链接:https://www.haomeiwen.com/subject/lcgzphtx.html