栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

每天一个设计模式之单例模式(六种写法)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

每天一个设计模式之单例模式(六种写法)

每天一个设计模式之单例模式(六种写法)
  • 基本介绍
    • 意图
    • 典型例子
    • 典型应用
  • UML类图
  • 六种写法
    • 1. Eager模式
      • 优点
      • 缺点
      • 补充
    • 2. Lazy模式
      • 缺点
    • 3. 非线程安全的Lazy模式
      • 优点
      • 缺点
    • 4. 线程安全的Lazy模式
    • 5. 基于静态内部类实现单例
      • 原理
    • 6. 基于Enum实现单例
  • PLUS - 如果本文对你有帮助,可以随手扫个码,领个包再走!![在这里插入图片描述](https://img-blog.csdnimg.cn/d6bb2a99bd72400a938de8d4c374a841.jpeg =300x450)

基本介绍 意图

确保系统内某些类至多只有唯一一个实例。

典型例子
  1. java.lang.Runtime
  2. java.awt.Desktop
典型应用
  1. Configuration File
  2. Cache
  3. Logger
  4. drivers
  5. database connection
UML类图

六种写法 1. Eager模式
// 为何final
class final Singleton extends Serializable {
	// 一上来就实例化,eagerly;线程安全吗?
    private static Singleton instance = new Singleton();
    private Singleton() { }

    public static Singleton getInstance() {
        return instance;
    }
    // 这是什么方法,来自谁?
	private Object readResolve() throws ObjectStreamException {
        return instance;
    }
}
优点
  1. 简单
  2. 线程安全
缺点
  1. 类加载时就实例化,性能受到影响;
补充
  1. 如何保证线程安全?静态成员变量,在类初始化的时候创建,由jvm保证线程安全;
  2. final 的作用?防止子类覆盖父类方法破坏单例;
  3. readResolve 的作用?加入readResolve方法,在反序列化时就会采用 readResolve 返回的对象,而不是反序列化生成的对象,从而防止反序列化破坏单例;
2. Lazy模式
class SingletonLazy {
    // 延迟实例化
    private static SingletonLazy instance = null;
    private SingletonLazy() { }
    // 多线程访问会怎样
    public static SingletonLazy getInstance() {
        if (instance == null)
            instance = new SingletonLazy();
        return instance;
    }
}
缺点
  1. 线程不安全;
3. 非线程安全的Lazy模式
class SingletonLazySafe {
    // 延迟实例化
    private static SingletonLazySafe instance = null;
    // 有没有什么问题?
    public static synchronized SingletonLazySafe getInstance() {
        if (instance == null)
            instance = new SingletonLazySafe();
        return instance;
    }

    private SingletonLazySafe() { }
}
优点
  1. 线程安全
缺点
  1. 即使已经存在实例了,依然需要走同步方法,性能受到影响;
4. 线程安全的Lazy模式
class SingletonDoubleCheck {
    // 延迟实例化,volatile 的作用?
    private static volatile SingletonDoubleCheck instance = null;
    public static SingletonDoubleCheck getInstance() {
        if (instance == null) {
            synchronized(SingletonDoubleCheck.class) {
            	// 这一次检查的意义是?
            	if (instance == null)
	                instance = new SingletonDoubleCheck();
            }
        }
        return instance;
    }

    private SingletonDoubleCheck() { }
}
  1. volatile 的作用
    防止 SingletonDoubleCheck 在实例化的时候指令重排,导致别的线程获得实例的时候虽不为空,但还未赋值;
  2. 为何要做第二次检查?如果没有第二次检查,如果线程1暂停在 synchronized 外面,线程2在 new SingletonDoubleCheck,那么线程2出去之后,线程1进来,它就又new了一次;
  3. 但是两次检查就安全了吗?还不!因为 new SingletonDoubleCheck() 是一个复合操作;
    初始化对象的过程:
    1) 分配内存
    2) 初始化对象
    3)设置instance指向刚分配的地址
    发生指令重排可能会改变123 的顺序变成132,这时候对象可能还没有初始化完就已经实例化了。
    volatile 关键字有可见性,禁止指令重排的功能。所以距离线程安全就差这一步了;
5. 基于静态内部类实现单例
class SingletonStaticInnerClass {
    public static SingletonStaticInnerClass getInstance() {
        return SingletonHolder.instance;
    }

    private static class SingletonHolder {
        private static SingletonStaticInnerClass instance = new SingletonStaticInnerClass();
    }

    private SingletonStaticInnerClass() { }
}
原理
  1. JVM保证只有在调用getInstance的时候才会去加载内部类且初始化单例;
6. 基于Enum实现单例
enum  SingletonInEnum {
    INSTANCE;

    public void doSomething() {
        
    }
}

参考:

  1. https://blog.csdn.net/MpenggegeM/article/details/123415319
  2. https://dzone.com/articles/java-singletons-using-enum
  3. https://www.java67.com/2020/05/5-ways-to-implement-singleton-design.html
  4. https://www.geeksforgeeks.org/singleton-design-pattern-introduction/?ref=rp5.
PLUS - 如果本文对你有帮助,可以随手扫个码,领个包再走!
转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1040413.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号