单例模式
懒汉型
实现了延迟加载,单线程无需加锁,多线程可以通过方法加锁完成线程安全,但效率奇低,因为绝大部分场景只是获取单例,而无需加载。
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
饿汉型
很好的避免了多线程问题。但由于类装载时就创建了实例,没有实现延迟加载,从而降低内存使用效率。
public class Singleton {
private final static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
静态内部类
实现了线程安全和延迟加载。
静态内部类在Java语言中是一个很特殊的类,跟普通的静态类以及非静态的内部类都有很大的差异。因为Java机制规定,内部类Holder只有在getInstance()方法第一次调用的时候才会被加载,而且其加载过程是线程安全的(实现线程安全)。
public class Singleton {
private Singleton() {
}
private static class Holder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return Holder.INSTANCE;
}
}
枚举型
《Effective Java》提出的,实现了自由序列化、线程安全和延迟加载。
INSTANCE作为类的引用,是公共静态的。但在类加载中,INSTANCE不会初始化,第一次访问会自动初始化(线程安全)。
public enum Singleton {
INSTANCE;
private Singleton() {
}
public Singleton getInstance() {
return INSTANCE;
}
}
双重校验锁
在线程安全的前提下做优化。这里仿照EhCache中的单例方式编写。因为new Singleton()并不是原子的,所以实例化后应尽快返回引用,避免其他线程进行多次实例。
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getSingleton() {
if (instance != null) {
return instance;
}
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
}