1、懒汉
优点:
- 简单
- 懒加载
缺点
- 同步调用,性能差
public class Singleton implements Serializable {
private static Singleton singleton = null;
private Singleton() {
}
public synchronized static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
// 防止反序列化创建对象不一致
private Object readResolve() {
return singleton;
}
public static void main(String[] args) {
System.out.println(Singleton.getInstance());
}
}
2、饿汉
优点:
- 简单
缺点
- 同步调用,性能差
- 占用资源
public class Singleton implements Serializable {
private static final Singleton singleton = new Singleton();
private Singleton() {
}
public synchronized static Singleton getInstance() {
return singleton;
}
// 防止反序列化创建对象不一致
private Object readResolve() {
return singleton;
}
public static void main(String[] args) {
SingletonIn.Holder a = new SingletonIn.Holder();
System.out.println(Singleton.getInstance());
}
}
3、双校验
优点:
- 同步代码块少
- 性能高
- 懒加载
缺点
- 代码复杂
public class Singleton implements Serializable {
private static volatile Singleton singleton = null;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
public static void main(String[] args) {
System.out.println(Singleton.getInstance());
}
// 防止反序列化创建对象不一致
private Object readResolve() {
return singleton;
}
}
4、内部类
优点:
- 代码简洁
- 静态内部类不被引用时就不会加载,实现真正的懒加载
缺点
- 通过内部类访问
public class Singleton {
static {
System.out.println("Initialize class SingletonIn");
}
private Singleton() {
}
public static class Holder {
static {
System.out.println("Initialize class Holder");
}
// 这里的私有没有什么意义
/* private */static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
// 外围类能直接访问内部类(不管是否是静态的)的私有变量
return Holder.instance;
}
public static void main(String[] args) {
System.out.println(Singleton.getInstance());
}
}
5、枚举
优点:
- 简洁
- 线程安全(编译后为static final 常量对象,Java类的加载和初始化是同步的。)
- 不会被反序列化破坏(枚举的反序列化并不是通过反射实现的,而是通过java.lang.Enum的valueOf方法来根据名字查找枚举对象)
无缺点!
public enum Singleton {
INSTANCE;
private void doSomething() {
System.out.println(1);
}
public static void main(String[] args) {
Singleton.INSTANCE.doSomething();
}
}