饿汉式
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
还有一个变种:静态代码块式
public class Singleton {
private static Singleton instance;
static {
instance = new Singleton();
}
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
缺点:没有懒加载。如果没有用到这个单例。造成浪费。
懒汉式
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
缺点:虽然有了懒加载,但只能在单线程中使用。
如果要在多线程中使用,就要同步。但是效率太低了。
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
双重校验
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
缺点:由于有序性问题,还是有问题。详细如下:
instance = new Singleton();这条语句不是原子的。需要做下面操作:
- 分配内存空间
- 初始化对象
- 内存地址指向instance
因为有指令重排的优化,步骤2和3可能颠倒。从而出现空指针问题。
所以千万不要忘了加volatile。防止指定重排。
静态内部类
public class Singleton {
private Singleton() {}
private static class SingletonInstance {
private static final Singleton singleton = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.singleton;
}
}
类装载机制保证线程安全性。比双重检查简单多了。
但是又要考虑新的问题了,不能防止反序列化方式,生成多个对象。
枚举方式
public enum Singleton {
INSTANCE;
Singleton() {}
public void getName() {}
}
线程安全的同时,还有防止反序列化生成多个对象。