单例模式实现

1 饿汉式

/**
 * @author :wyaoyao
 * @date : 2020-04-06 14:32
 * 单例模式:饿汉式
 * 线程安全
 * 但是在不使用的时候占用内存,因为通过static是类主动加载,不能能够懒加载
 */
public class SingletonSimple1 {

    private static final SingletonSimple1 instance = new SingletonSimple1();

    // 构造私有化。不允许外部调用
    private SingletonSimple1() {
    }

    public static SingletonSimple1 getInstance() {
        return instance;
    }
}
  • 线程安全
  • 但是在不使用的时候占用内存,通过static是类主动加载,不能能够懒加载

测试

// 测试
@Test
public void test() {
    SingletonSimple1 instance1 = SingletonSimple1.getInstance();
    SingletonSimple1 instance2 = SingletonSimple1.getInstance();
    Assert.assertTrue(instance1 == instance2);

}

懒汉式

/**
 * @author :wyaoyao
 * @date : 2020-04-06 14:41
 * 饿汉式:懒加载
 */
public class SingletonSimple2 {
    private static SingletonSimple2 instance;

    private SingletonSimple2(){

    }

    // 存在线程安全问题
    public static SingletonSimple2 getInstance(){
        if(null == instance){
            instance = new SingletonSimple2();
        }
        return instance;
    }
}
  • 这个懒加载,在使用的时候才会创建对象,但是线程不安全

测试

// 测试,构建100线程去创建对象,测试是否线程安全
@Test
public void test2() {
    for (int i = 0; i<100; i++){
        new Thread(()->{
            SingletonSimple2 instance = SingletonSimple2.getInstance();
            System.out.println(instance);

        },"T"+i).start();
    }

    /**
     * 不安全,并不是单例的,SingletonSimple2@608f35ee,SingletonSimple2@5617e729
     * study.wyy.concurrency.designpatterns.singleton.SingletonSimple2@608f35ee
     * study.wyy.concurrency.designpatterns.singleton.SingletonSimple2@5617e729
     * study.wyy.concurrency.designpatterns.singleton.SingletonSimple2@7df5ed4e
     * study.wyy.concurrency.designpatterns.singleton.SingletonSimple2@7df5ed4e
     * study.wyy.concurrency.designpatterns.singleton.SingletonSimple2@7df5ed4e
     */
}

在这里插入图片描述

解决懒汉式的线程不安全

方案一
   // 加锁
    public synchronized static SingletonSimple2 getInstance(){
        if(null == instance){
            instance = new SingletonSimple2();
        }
        return instance;
    }

问题

  • 除了第一次是创建,以后都是读的操作,每次都会加锁,效率不高
方案二

double check

public class SingletonSimple3 {
    private static SingletonSimple3 instance;

    private SingletonSimple3(){

    }

    public static  SingletonSimple3 getInstance(){
        if(null == instance){
            synchronized (SingletonSimple3.class){
                if(null == instance){
                    instance = new SingletonSimple3();
                }
            }
        }
        return SingletonSimple3.instance;
    }

}

在这里插入图片描述

也存在问题:可能会引起npe

解决这个问题很简单,使用volatile关键字即可

public class SingletonSimple3 {
    private static volatile SingletonSimple3 instance;

    private SingletonSimple3(){

    }

    public static  SingletonSimple3 getInstance(){
        if(null == instance){
            synchronized (SingletonSimple3.class){
                if(null == instance){
                    instance = new SingletonSimple3();
                }
            }
        }
        return SingletonSimple3.instance;
    }

}

ClassHolder

  • 支持懒加载
  • 线程安全
  • 不会npe
public class SingletonSimple5 {
    private SingletonSimple5(){
    }

    private static class InstanceHolder {
        private final static SingletonSimple5 instance = new SingletonSimple5();
    }

    public static SingletonSimple5 getInstance(){
        return InstanceHolder.instance;
    }

}

枚举方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值