Singleton单例模式

2020-04-08  本文已影响0人  silence_J

应用场景

只需要一个实例

饿汉式

/**
 *饿汉式:
 *
 * 类加载到内存后,就实例化一个单例,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

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保证单例
 * 加载外部类时不会加载内部类,这样可以实现懒加载
 */
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(){};

}
上一篇 下一篇

猜你喜欢

热点阅读