单例模式
单例模式有两个特点:
- 保证一个类只有一个实例
- 为该实例提供一个全局访问节点
为什么要使用单例模式:
通常是为了集中管理某种共享资源(如数据库,文件等)。
单例模式的实现步骤:
- 将默认构造函数设置为私有;
- 新建一个静态构建方法作为构造函数。 该函数会调用私有构造函数来创建对象, 并将其保存在一个静态成员变量中。 此后所有对于该函数的调用都将返回这一缓存对象。
饿汉式
public class SingletonObj {
private SingletonObj() {}
private static final SingletonObj instance = new SingletonObj();
public static SingletonObj getInstance() {
return instance;
}
}
懒汉式
public class SingletonObj {
private static SingletonObj instance;
private SingletonObj() {}
public synchronized static SingletonObj getInstance() {
if (instance == null) {
instance = new SingletonObj();
}
return instance;
}
}
双重检查锁
public class SingletonObj {
private static volatile SingletonObj instance;
private SingletonObj() {}
public static SingletonObj getInstance() {
if (instance == null) {
synchronized(SingletonObj.class) {
if (instance == null) {
instance = new SingletonObj();
}
}
}
}
}
为了提高懒汉式的性能,只有在实例不存在的情况下才进行加锁。
对instance
对象添加volatile
关键字,是为了解决有序性(指令重排)问题。不加的话,JVM 可能在构造函数内的属性还未初始化完成时,就返回对象,会导致其他线程可能会获取到不完整的对象。
静态内部类实现
public class SingletonObj {
private SingletonObj() {}
private static class InstanceHolder {
private static SingletonObj instance = new SingletonObj();
}
public static SingletonObj getInstance() {
return InstanceHolder.instance;
}
}
枚举类实现
public class SingletonObj {
private SingletonObj() {}
private enum Singleton {
INSTANCE;
private static SingletonObj instance;
Singleton() {
instance = new SingletonObj();
}
private SingletonObj getInstance() {
return instance;
}
}
public static SingletonObj getInstance() {
return Singleton.INSTANCE.getInstance();
}
}