设计模式系列—单例设计模式( 二 )
/** * 懒汉式(线程安全 , 同步方法) */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 实例化对象 , 也避免了反复进行方法同步 。
静态内部类代码示例
package com.niuh.designpattern.singleton.v7;/** * 静态内部类完成 , 推荐使用 */public class Singleton {// 添加 volatile 关键字 , 防止指令重排private static volatile Singleton instance;// 构造函数私有化private Singleton() {}// 写一个静态内部类 , 该类中有一个静态属性 Singletonprivate static class SingletonInstance {privatestatic final Singleton INSTANCE = new Singleton();}// 提供一个静态的公有方法 , 直接返回 SingletonInstance.INSTANCEpublic static synchronized Singleton getInstance() {return SingletonInstance.INSTANCE;}}
优缺点- 本质上是利用类的加载机制来保证线程安全
- 只有在实际使用的时候 , 才会触发类的初始化 , 所以也是懒加载的一种形式 。
- 优点:避免了线程不安全 , 利用静态内部类特点实现延迟加载 , 效率高
枚举代码示例
package com.niuh.designpattern.singleton.v8;/** * 使用枚举 , 可以实现单例, 推荐 */public enum Singleton {INSTANCE; // 属性public void hello() {System.out.println("hello word~");}} class SingletonTest08 {public static void main(String[] args) {Singleton instance1 = Singleton.INSTANCE;Singleton instance2 = Singleton.INSTANCE;System.out.println(instance1 == instance2);System.out.println(instance1.hashCode());System.out.println(instance2.hashCode());instance1.hello();}}
优缺点- 天然不支持反射创建对应的实例 , 且有自己的反序列化机制
- 利用类加载机制保证线程安全
反射攻击实例我们拿饿汉模式作为例子进行测试 , 饿汉模式的代码如下:
package com.niuh.designpattern.singleton.reflect;/** * 饿汉模式防止反射攻击 */public class HungrySingleton {private static final HungrySingleton instance;private HungrySingleton(){}static {instance = new HungrySingleton();}public static HungrySingleton getInstance(){return instance;}private Object readResolve(){return instance;}}
- 看不上|为什么还有用户看不上华为Mate40系列来看看内行人怎么说
- 采用|消息称一加9系列将推出三款新机,新增一加9E
- 世代|Z星球——腾讯布局Z世代教育社交的新尝试
- 脉搏|把握时代发展脉搏,尽展巴蜀版权风采——2020年成都数字版权交易博览会成功举办
- 系列|首销300000台!红米Note 9系列,或许可以说恭喜你了?
- 系列|联想碰瓷Redmi后正式复活乐檬手机!乐檬K12系列即将到来
- 系列|Redmi Note9系列三剑客来袭,差别到底有多大?该如何选择?
- 超强|RedmiNote9系列发布!天玑800U赋予超强5G性能
- 回顾|华为P系列回顾
- 情况|刚发布就卖出30万台:红米Note9系列稳了,销售情况追赶前代