单例模式
标签: 设计模式
单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点的模式。属于建造型模式。
1. 简单方式, 懒加载,单线程
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
2. 懒加载,考虑多线程,但锁住整个get方法,效率低
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3. 考虑多线程,不加锁,效率高,但饿汉加载,浪费内存(推荐)
public class Singleton {
//基于classloder机制避免多线程的同步问题
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
4. 双重校验锁,多线程,效率高,实现复杂
public class Singleton {
private volatile static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
//99%的情况下instance不为null,因此加锁概率很少,总体效率高
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
5.静态内部类,类似情况3,但懒加载,多线程,比较简单
public class Singleton {
private static class SingletonHolder {
//既基于classloder机制避免多线程的同步问题,又懒加载
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
6.使用枚举方法
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
总结:
(1)一般情况下,不建议使用第 1 种和第 2 种懒汉方式,建议使用第 3 种饿汉方式。
(2)只有在要明确实现 lazy loading 效果时,才会使用第 5 种登记方式。
(3)如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。
(4)如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式。