设计模式系列—单例设计模式( 二 )
这种单例模式可用 , 但是如果不用 , 可能会造成内存的浪费 。
懒汉式(线程不安全)代码示例package com.niuh.designpattern.singleton.v3;/** * * 懒汉式(线程不安全) */public class Singleton {private static Singleton instance;// 构造函数私有化private Singleton() {}// 提供一个静态的公共方法 , 当使用到该方法时 , 才创建 instance , 即懒汉式public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}}class SingletonTest02 {public static void main(String[] args) {// 测试for (int i = 0; i< 100; i++) {new Thread(() ->System.out.println(Singleton.getInstance().hashCode())).start();}}}
优缺点
- 起到了 懒加载 的效果 , 但是只能在 单线程下使用;
- 如果在多线程下 , 一个线程进入了 if(instance == null) 判断语句块 , 可能另外一个线程也通过了这个语句判断 , 这是会产生多个实例 , 所以在多线程环境下不可使用这种方式 。
懒汉式(线程安全 , 同步方法)代码示例
/** * 懒汉式(线程安全 , 同步方法) */public class Singleton {private static Singleton instance;// 构造函数私有化private Singleton() {}// 提供一个静态的公有方法 , 加入同步处理的代码 , 解决线程安全问题public static synchronizedSingleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}}
注:加入关键字保证线程安全问题 synchronized优缺点
- 虽然加入保证线程安全的关键字 , 解决线程安全问题(其实实际上并不一定线程安全:编译器(JIT),CPU 有可能对指令进行重排序)
- 效率低下 , 每个线程在想获得实例的时候 , 执行 getInstance 方法都要进行同步 。 方法的同步效率太低 。
懒汉式(线程安全 , 同步代码块)代码示例
/** * 懒汉式(线程安全 , 同步代码块) */public class Singleton {private static Singleton instance;// 构造函数私有化private Singleton() {}// 提供一个静态的公有方法 , 加入同步处理的代码 , 解决线程安全问题public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {instance = new Singleton();}}return instance;}}
优缺点虽然对加锁处做了一定优化 , 总体优缺点同上面一致 。双重检查(DCL)代码示例
/** * 双重检查 DCL */public class Singleton {// 添加 volatile 关键字 , 防止指令重排private static volatile Singleton instance;// 构造函数私有化private Singleton() {}// 提供对外引用的静态方法 , 使用双重检查机制 double checkpublic static Singleton getInstance() {if (instance == null) { // Double Check Lock// 双重检查synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}}
编译器(JIT),CPU 有可能对指令进行重排序 , 导致使用到尚未初始化的实例 , 可以通过添加volatile 关键字进行修饰优缺点
- Double-Check 概念是多线程开发中常使用到的 , 如代码中所示 , 我们进行了两次 if(singleton== null) 检查 , 这样就可以保证线程安全了
- 实例化代码只用执行一次 , 后面在进行访问的时候 , 判断 if(singleton== null) , 直接 return 实例化对象 , 也避免了反复进行方法同步 。
推荐阅读
- 三星新旗舰Galaxy S21系列发布倒计时3天
- 改变网络化办公 揭秘夏普新复合机系列
- 网络双面提速办公 夏普发布全新复印机系列
- 电脑报2020年度获奖产品:引领智能商务无线投影时代的明基E系列商务投影机
- 手机必须双扬声器 魅族17系列告诉你这不是噱头
- 三星S21系列再次3C认证 充电器或成为“可选”配件
- 三星竟为Galaxy S21系列提供900多种颜色配置
- 摩托罗拉发布2021款Moto G系列产品 内建大容量电池169美元起价
- 影像旗舰vivo X60系列正式开售 斩获多个线上平台双冠军
- 对标AirPods系列 JBL推出2021新款无线耳机阵容