使用场景
只需要单个实例,比如说线程池、缓存等,如果存在两个不同的实例,就会引发种种问题。单例模式的设计就是为了保持永远只有一个实例。但是由于性能、存储上的考虑,单例模式有以下几种实现方式,可根据应用场景自行选择。
demo1 普通模式
public class Singleton {
private static SingleTon uniqueInstance;
private static Singleton getInstance() {
uniqueInstance = new Singleton();
}
}
demo2 延迟实例化模式
public class Singleton {
private static SingleTon uniqueInstance;
//添加synchronized防止两个线程同时进入到该方法
//避免实例化过程进行两次
private synchronized static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
demo3 急切实例化模式
public class Singleton {
//保证线程安全,但是JVM在加载这个类时会马上创建实例
//对性能会产生影响
private static SingleTon uniqueInstance = new Singleton();
private static Singleton getInstance() {
return uniqueInstance;
}
}
demo4 双重检查加锁
public class Singleton {
//volatile确保变量被初始化后,多个线程能正确的处理该变量
private volatile static SingleTon uniqueInstance;
private static Singleton getInstance() {
if (uniqueInstance == null) {
//避免单例被初始化两次
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
关键点
- 私有的构造器
- 一个静态方法和一个静态变量
需要注意的点
- 在性能和资源的限制下选择最合适的方案
特定环境下的问题
- Java1.2之前, 单例没有全局引用时会被垃圾回收器回收, 1.2之后已经修复.
- 每个类加载器都定义了一个命名空间, 如果有多个类加载器, 就有可能会将一个类加载多次, 产生多个单例并存的情况. 解决办法: 自行指定类加载器, 并指定同一个类加载器.