Java 懒汉式单例模式
懒汉式单例模式
public class Singleton{
private Singleton(){};
private static Singleton single = null;
//存在线程安全问题
public static Singleton getInstance(){
if(single==null)
single = new Singleton();
return single;
}
}
public class Singleton{
private Singleton() {};
//懒汉式
private static Singleton single = null;
//解决线程安全问题
public static Synchronized Singleton getInstance(){
if(single==null){
single = new Singleton();
}
return single;
}
}
public class Singleton{
private Singleton() {};
//双重检查锁定
private volatile static Singleton single1 = null;
public static Singleton getInstance(){
if(single1==null){
synchronized(Singleton.class){
if(single1==null)
single1 = new Singleton();
}
}
return single;
}
}
双重检查锁定有一个地方要注意,single 要用 volatile 修饰,因为 JMM 模型的特点,要保证内存的可见性,以及避免无序写入
public class Singleton{
private Singleton(){};
//静态内部类方式
//final 解决多线程问题,也减去了判断 single 是否实例化的性能
public static class LazyHolder{
private static final Singleton ISTANCE = new Singleton();
}
public static Singleton getInstance(){
return LazyHolder.INSTANCE;
}
}
用内部类实现延迟加载
饿汉式单例模式
区别于懒汉式是类初始化时就会生成实例对象,而懒汉式是调用 getInstance 方法时才会生成实例
public class Singleton{
//final 修饰,线程安全,且唯一
private final static Singleton single = new Singleton();
private Singleton(){};
public static Singleton getInstance(){
return single;
}
}
登记式单例模式
登记式单例模式(Registry Singleton)是一种设计模式,确保一个类只有一个实例,并提供全局访问点。它通过在类内部持有一个静态实例并通过静态方法访问该实例来实现。以下是这种模式的基本实现步骤:
实现步骤
- 私有构造函数 :确保外部无法直接创建类的实例。
- 静态变量 :持有类的唯一实例。
- 静态方法 :提供全局访问点,返回唯一实例。
示例代码(Java)
public class RegistrySingleton {
// 持有唯一实例
private static RegistrySingleton instance;
// 私有构造函数
private RegistrySingleton() {}
// 静态方法获取实例
public static RegistrySingleton getInstance() {
if (instance == null) {
instance = new RegistrySingleton();
}
return instance;
}
}
特点
- 延迟加载 :实例在第一次使用时创建。
- 线程安全 :基本实现不是线程安全的,可以通过添加
synchronized
关键字或使用其他线程安全机制来改进。
适用场景
适合需要确保只有一个实例且提供全局访问点的情况,比如配置管理、日志记录等。
如果想深入了解具体的实现细节或其他变种,随时告诉我!
懒汉和饿汉比较
除了实例对象创建的时间,还有懒汉是非线程安全的只有自己实现,而饿汉是线程安全的。饿汉式无论用不用该实例都已经分配了内存,但第一次调用时速度也更快。
其次是,上面懒汉式的几种写法区别。
public static Synchronized Singleton getInstance()
是同步的,效率会低,毕竟大多数时并不需要同步- 相比而言,双重检查锁定会先判断 single 是否空来减少同步保证,但也实现了线程安全
- 静态内部类方式利用了 classloader 的机制来保证初始化 instance 时只有一个线程
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 深入理解 Java 虚拟机
下一篇: 包管理工具 apt 的使用
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论