Java单例模式(懒汉 饿汉 双检锁)

单例模式:一种创建型设计模式 让你能够保证一个类只有一个实例 并提供一个访问该实例的全局节点

方法为私有化构造函数,在类中定义静态实例(先new为饿汉 后new为懒汉)

在方法定义静态方法,返回唯一实例

下面介绍三种单例模式java代码写法

1。懒汉式(需要用时再申请)缺点:有线程不安全风险  

(2021/1/18更新:为什么不安全呢?

竞态条件的类型“先检查后执行”的一种情况——延迟初始化

假设有线程A B同时执行这个方法,A看到是null的,取决于时序、线程调度方式,如果B同样需要看到是null的(未初始化完成),则会出现覆盖)

class lhan {
    private int address = 1999;
    private static lhan instance;
    //私有化构造函数 外部只能用实例调用 无法新声明新实例
    private lhan() {
    }
     void put(int k) {
        address = k;
        return;
    }
     int get() {
        return address;
    }
    //返回唯一实例
    public static lhan getInstance() {
        if (instance == null) {
            instance = new lhan();
        }
        return instance;
    }
}

2.饿汉式(不管是否调用 先申请)  优点:线程安全。   缺点:如果不调用的话浪费内存

class ehan{
    private int age=20;
    private ehan(){};//私有化构造函数
    private static ehan instance=new ehan();
    void put(int k) {
        age = k;
        return;
    }
    public int get() {
        return age;
    }
    public static ehan getInstance()
    {
        return instance;
    }
}

3.双检锁式(综合了饿汉 懒汉的优点 并改正了其缺点)

这样既保证了线程安全,又比直接上锁提高了执行效率,还节省了内存空间。

class DoubleCheack{
    private static DoubleCheack instance;
    private int age=1;
    private DoubleCheack(){};
    void put(int k) {
        age = k;
        return;
    }
    public int get() {
        return age;
    }
    public static DoubleCheack getInstance()
    {
        if(instance==null) {//先判断是否为null 后上锁进行初始化
            synchronized (DoubleCheack.class) {
                if (instance == null)//将对象上锁之后再次判断 是否有别的线程初始化了
                    instance = new DoubleCheack();
            }
        }
        return instance;
    }
}

主函数测试用例(双检锁)

 无论对于几个实例内数据如何变动 都指向一个唯一实例(instance)

参考博文:

https://blog.csdn.net/absolute_chen/article/details/93380566

原文地址:https://www.cnblogs.com/cckong/p/13803832.html