单例模式(Singleton)
Singleton模式确保每个Java类加载器只能有一个已有的实例并提供对其的全局访问,单例可以节省内存,加快对象访问速度
适用场景
需要频繁实例化然后销毁的对象创建对象耗时长或占用资源大,但又要经常用到的对象带有状态的工具类对象频繁访问数据库或文件的对象,一次实例化多次使用
单例种类
饿汉式:类加载的时候就被初始化,静态字段中实例化懒汉式:延迟加载,调用getInstance()方法时实例化双重检查锁:延迟加载,对上一个进行优化的方式 以上都是线程安全的
代码示例
饿汉式
public final class HungrySingleton {
private static final HungrySingleton INSTANCE
= new HungrySingleton();
private HungrySingleton() {
}
public static HungrySingleton
getInstance() {
return INSTANCE
;
}
}
懒汉式(私有内部类方式)
public final class LazyLoadedSingleton {
private LazyLoadedSingleton() {
System
.out
.println("init LazyLoadedSingleton");
}
public static LazyLoadedSingleton
getInstance() {
return HelperHolder
.INSTANCE
;
}
private static class HelperHolder {
public static final LazyLoadedSingleton INSTANCE
= new LazyLoadedSingleton();
}
}
懒汉式(synchronized方式)
public final class LazyLoadedSingleton2 {
private static LazyLoadedSingleton2 instance
;
private LazyLoadedSingleton2() {
}
public static synchronized LazyLoadedSingleton2
getInstance() {
if (instance
== null
) {
instance
= new LazyLoadedSingleton2();
}
return instance
;
}
}
双重检查锁
public final class DoubleCheckLockingSingleton {
private static volatile DoubleCheckLockingSingleton instance
;
private DoubleCheckLockingSingleton() {
if (instance
!= null
) {
throw new IllegalStateException("Already initialized.");
}
}
public static DoubleCheckLockingSingleton
getInstance() {
DoubleCheckLockingSingleton result
= instance
;
if (result
== null
) {
synchronized (DoubleCheckLockingSingleton
.class) {
result
= instance
;
if (result
== null
) {
instance
= result
= new DoubleCheckLockingSingleton();
}
}
}
return result
;
}
}
FAQ
单例多种实现方式中为什么要用双重检查锁的方式来实现单例? 在延迟加载中,保证线程安全可以直接在getInstance()方法中直接使用synchronized来保证线程安全,但性能一个问题,也就是说每次调用getInstance()方法都需要线程同步(加锁其实只需要在第一次初始化的时候用到),性能不高
更多内容可以参考我的另一篇文章:单例模式之双重检查锁(double check locking)的发展历程
如果你喜欢我的文章,记得一键三连(不要下次一定)