单例类在整个程序中只能有一个实例,这个类负责创建自己的对象,并确保只有一个对象被创建。
代码实现要点
a) 私有构造器
b) 持有该类的属性
c) 对外提供获取实例的静态方法
(面试可手写)
饿汉式:线程安全、反射不安全、反序列化不安全
public class Singleton1 implements Serializable {
private static Singleton1 singleton1=new Singleton1();
private Singleton1() {}
public static Singleton1 getInstance() {
return singleton1;
}
private Object readResolve() {
return singleton1;
}
}
登记式:(静态内部类):线程安全、防止反射攻击、反序列化不安全
public class Singleton2 {
private static class SingletonHolder {
private static Singleton2 singleton2=new Singleton2();
}
private Singleton2() {
System.out.println("Singleton2 loaded");
if (SingletonHolder.singleton2 != null) {
throw new IllegalStateException();
}
}
public static Singleton2 getInstance() {
return SingletonHolder.singleton2;
}
}
枚举式:线程安全、支持序列化、反序列化安全、防止反射攻击
public enum Singleton3 {
INSTANCE{
@Override
protected void doSomething() {
System.out.println("method doSomething start...");
}
};
protected abstract void doSomething();
}
懒汉式:线程不安全、延迟加载、(两种加同步,效率低)一种是synchronized代码块一种是synchronized修饰方法
public class Singleton4 {
private static Singleton4 instance = null;
private Singleton4() {
}
public static Singleton4 getInstance() {
if (instance == null) {
instance = new Singleton4();
}
return instance;
}
}
(面试可手写)
双检锁:线程安全、volatile
public class Singleton7 {
private static volatile Singleton7 instance = null;
private Singleton7() {
}
public static Singleton7 getInstance() {
if (instance == null) {
synchronized (Singleton7.class) {
if (instance == null) {
instance = new Singleton7();
}
}
}
return instance;
}
}
################
instance=new Singleton7()会执行如下操作:
(1) 分配对象内存空间
(2) 初始化对象
(3) instance指向(1)中分配的空间
在某些编译器上,可能出现指令重排:
(1) 分配对象内存空间
(2) instance指向(1)中分配的空间 (但此时对象没有初始化)
(3) 初始化对象
##################
(面试加分项)
ThreadLocal:不加锁,以空间换时间,为每个线程提供变量的独立副本,可以保证各自线程中是单例的,但是不同线程之间不保证
public class Singleton8 {
private static Singleton8 instance = null;
private Singleton8() { }
private static final ThreadLocal<Singleton8> threadLocalSingleton = new ThreadLocal<Singleton8>() {
@Override
protected Singleton8 initialValue() {
return new Singleton8();
}
};
public static Singleton8 getInstance() {
return threadLocalSingleton.get();
}
}
(面试加分项)
CAS:无锁乐观策略,线程安全
public class Singleton9 {
private static final AtomicReference<Singleton9> instance = new AtomicReference<>();
private Singleton9() {
System.out.println("Singleton9 Loaded");
}
public static final Singleton9 getInstance() {
for (; ; ) {
Singleton9 current = instance.get();
if (current != null) {
return current;
}
current = new Singleton9();
if (instance.compareAndSet(null, current)) {
return current;
}
}
}
}