饿汉式:
- 类加载时就初始化,浪费内存,不能延迟加载;
- 基于
classloader机制避免了多线程的同步问题,线程安全; - 没有加锁,调用效率高。
public class Singleton{
private static Singleton INSTANCE = new Singleton();
private Singleton(){}
public 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;
}
}
双重校验锁:在加锁之前判断是否为空,可以确保 instance 不为空的情况下,不用加锁,可以直接返回。 加锁之后,还需要判断 instance 是否为空,是为了防止在多线程并发的情况下,会实例化多个对象。例如:线程 a 和线程 b 同时调用 getInstance 方法,假如同时判断 instance 都为空,这时会同时进行抢锁。假如线程 a 先抢到锁,开始执行 synchronized 关键字包含的代码,此时线程 b 处于等待状态。线程 a 创建完新实例了,释放锁了,此时线程 b 拿到锁,进入 synchronized 关键字包含的代码,如果没有再判断一次 instance 是否为空,则可能会重复创建实例。
public class Singleton{
private volatile static Singleton INSTANCE;
private Singleton(){}
public static Singleton getInstance(){
if(INSTANCE == null){
synchronized(Singleton.class){
if(INSTANCE == null){
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
静态内部类:
- 利用了
classloader机制来保证初始化instance时只有一个线程,线程安全; - 只有通过显式调用
getInstance方法时,才会显式装载静态内部类,从而实例化instance,延迟加载。
public class Singleton{
private static class InnerClass{
public final static Singleton INSTANCE = new Singleton();
}
private Singleton(){}
public static Singleton getInstance(){
return InnerClass.INSTANCE;
}
}
枚举:能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。但是不是延迟加载的。
public enum Singleton{
INSTANCE;
}