单例模式你能写出多少种方案?

单例模式:保证在内存中只有一个实例!

  1. 饿汉式
    类加载到内存后就实例化一个单例,JVM保证线程安全
    *简单实用!推荐!
/**单例模式:保证在内存中只有一个实例!
 3. 饿汉式
 4. 类加载到内存后就实例化一个单例,JVM保证线程安全
 *简单实用!推荐!
 5.  6. */
public class Mgr01 {
    //创建Mgr01的一个对象
    private static final Mgr01 INSTANCE = new Mgr01();
    //让构造函数成为private,这样类就不会被实例化
    private Mgr01() {
    }


    public static Mgr01 getInstance() {
        return INSTANCE;
    }

    
    public static void main(String[] args) {
        Mgr01 mgr01 = Mgr01.getInstance();
        Mgr01 mgr02 = Mgr01.getInstance();
        System.out.println(mgr01 == mgr02);
    }

}

结果:

true

Process finished with exit code 0

2.懒汉式

  • 这种方式解决了在类加载的时候不会直接创建对象,但是这种方式出现了线程安全的问题
public class Mgr02 {

    private static Mgr02 INSTANCE = null;
    //让构造方法私有
    private Mgr02 (){};
    //创建方法
    public static Mgr02 getInstance(){
        try {
            Thread.sleep(10); //测试线程安全问题
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (INSTANCE == null){
            INSTANCE = new Mgr02();
        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()-> System.out.println(Mgr02.getInstance().hashCode())).start();
        }
    }
}

3.懒汉式的进阶版:给方法加 synchronized关键字保证线程安全

  • 但是还有进阶版(●’◡’●)
public class Mgr03 {
    //
    private static Mgr03 INSTANCE = null;
    //让构造方法私有
    private Mgr03 (){};
    //
    public synchronized static Mgr03 getInstance(){
        if(INSTANCE == null){
            INSTANCE = new Mgr03();
        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()-> System.out.println(Mgr03.getInstance().hashCode())).start();
        }

    }
}

4.还可以给代码块加synchronized关键字保证线程安全

public class Mgr04 {
	//为什么要加volatile:①线程间可见  ②禁止指令重排序(半初始化过程会出现指令重排序的情况)
    private static volatile Mgr04 INSTANCE =null;
    private Mgr04 (){};
    public static Mgr04 getInstance(){
        if (INSTANCE == null){
            synchronized (Mgr04.class){
                if (INSTANCE == null){
                    INSTANCE = new Mgr04();
                }
            }
        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()-> System.out.println(Mgr04.getInstance().hashCode())).start();
        }
    }
}

这种方案采取双重判定,但是代码看上去很复杂。。因此出现了相对优美的方案。
单例模式的最优美的方案之一
5. 采用了静态内部类的方法

  • 但是还有最后一种完美的方案!继续往下看ヾ(≧▽≦*)o
public class Mgr05 {
    private Mgr05(){};
    public static class InstanceHolder{
        private static Mgr05 INSTANCE = new Mgr05();
    }

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

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()-> System.out.println(Mgr05.getInstance().hashCode())).start();
        }
    }
}

单例模式的最完美的方案出现了
6. 枚举单例!!!不仅安全而且代价量少,优美,最好的方案。


 * */
public enum  Mgr06 {
    INSTANCE;

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()-> System.out.println(Mgr06.INSTANCE.hashCode())).start();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值