单例模式(保证线程安全)

单例模式

单例是⼀种设计模式。单例模式是指整个程序中⼀个类只能有⼀个对象。

static修饰一个变量之后,这个变量就从⼀个普通的成员变量、属性变成了类对象的成员变量,⽽在JVM中⼀个类只有⼀个类对象,从⽽保证了static变量的唯⼀性。

饿汉模式

类一加载就完成初识化的方式成为饿汉模式

public class SingletonHungry {
    // 用static修饰变量,变量就是自己,并且赋初始值
    private static SingletonHungry instance = new SingletonHungry();
    // 构造方法私有化
    private SingletonHungry() {}
    /**
     * 提供一个对外获取实例对象的方法
     * @return instance
     */
    public static SingletonHungry getInstance () {
        return instance;
    }
}
public class Demo01_Singleton {
    public static void main(String[] args) {
        // 通过静态方法调用,获取单例
        SingletonHungry singleton01 = SingletonHungry.getInstance();
        SingletonHungry singleton02 = SingletonHungry.getInstance();
        SingletonHungry singleton03 = SingletonHungry.getInstance();
        // 分别打印
        System.out.println(singleton01);
        System.out.println(singleton02);
        System.out.println(singleton03);
    }
}

懒汉模式

为了避免程序启动的时候浪费过多的系统资源,当程序使用这个对象时再进行初始化,把这种模式叫做“懒汉模式。

public class SingletonLazy {
    // 定义一个类成员变量
    private static SingletonLazy instance = null;

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

    public static SingletonLazy getInstance() {
        // 在获取的成员变量的时候,判断一下是否已经初始创建
        // 如果没有创建则创建出来
       	if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }
}

懒汉模式在多线程环境下,可能出现线程安全的问题,那么就需要使用synchronized包裹初始化的代码块。

public class SingletonLazy {
    // 定义一个类成员变量
    private static SingletonLazy instance = null;
    // 构造方法私有化
    private SingletonLazy() {
    }
    public static SingletonLazy getInstance() {
        // 在获取的成员变量的时候,判断一下是否已经初始创建
        // 如果没有创建则创建出来
        synchronized (SingletonLazy.class) {
            if (instance == null) {
                instance = new SingletonLazy();
            }
        }
        return instance;
    }
}

初识化代码只执行一次,后续的线程在调用getInstance()时,依然会产生锁竞争,频繁的进行用户态和内存态之间的切换,非常浪费计算机资源。因此可以引进double check lock(DCL)的方式,在外层加一个非空校验,避免了无用

public class SingletonDCL {
    // 定义一个类成员变量
    private volatile static SingletonDCL instance;
    // 构造方法私有化
    private SingletonDCL() {
    }

    public static SingletonDCL getInstance() {
        // 为了让后面的线程不再获取锁,避免了锁竞争造成的资源浪费
        if (instance == null) {
            synchronized (SingletonDCL.class) {
                // 完成初始化操作,只执行一次
                if (instance == null) {
                    instance = new SingletonDCL();
                }
            }
        }
        // 返回实例对象
        return instance;
    }
}
public class Demo04_SingletonDCL {
    public static void main(String[] args) {
        // 创建多个线程,并获取单例对象
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(()->{
                // 获取单例对象,并打印
                SingletonDCL singletonDCL = SingletonDCL.getInstance();
                System.out.println(singletonDCL);
            });

            thread.start();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值