单例模式确保一个类只有一个实例,并提供一个全局访问点。
有些对象我们只需要一个,如线程池、缓存、日志对象、设备驱动等。事实上这些对象如果有多个实例,会造成许多问题。
简单示例
public class SimpleSingleton {
private static SimpleSingleton singleton;
private SimpleSingleton() {
}
public static SimpleSingleton getInstance() {
// 延迟加载,对资源敏感的对象特别重要。有可能某次运行中该对象并未被使用
if (singleton == null) {
singleton = new SimpleSingleton();
}
return singleton;
}
}
注:
- 非线程安全,多线程环境下可能会出现异常
静态变量
public class StaticSingleton {
// 类加载时就会被初始化
private static StaticSingleton singleton = new StaticSingleton();
private StaticSingleton() {
}
public static StaticSingleton getInstance() {
return singleton;
}
}
注:
- 线程安全,类加载时就会被初始化
- 但是,因为静态变量的控制权是在jvm手上,这么做有可能导致混乱,特别是当有许多类牵涉其中的时候。这么做常常会造成一些微妙的、不容易发现的和初始化次序有关的bug
同步方法
public class SyncSingleton {
private static SyncSingleton singleton;
private SyncSingleton() {
}
public static synchronized SyncSingleton getInstance() {
if (singleton == null) {
singleton = new SyncSingleton();
}
return singleton;
}
}
注:
- 线程安全,getInstance为同步方法
- 如果getInstance方法被多次使用,效率会下降很多,同步方法可能会造成程序执行效率下降100倍
双重检查加锁
public class SyncSingleton {
// volatile关键字声明的变量会立即感知到其他线程对此变量做出的修改(工作内存和主内存实时同步)
private static volatile SyncSingleton singleton;
private SyncSingleton() {
}
public static SyncSingleton getInstance() {
if (singleton == null) {
synchronized (SyncSingleton.class) {
if (singleton == null) {
singleton = new SyncSingleton();
}
}
}
return singleton;
}
}
注:
- 线程安全,多线程环境下优先选择
- 不支持jdk1.5(不包括)以下的版本
参考文章
1. Head First 设计模式