模式简介
定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
核心:私有构造方法、获取实例的静态方法
常见写法
- 懒汉式(线程不安全)
public class Singleton {
// 类自身保存的唯一实例 private
private static Singleton singleton;
// 构造方法私有化
private Singleton(){
}
public static Singleton getInstance() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
申明一个静态对象,调用getInstance() 获取实例时,如果实例为null,则初始化一个实例并返回,这种方式在多线程下是不安全的,不推荐使用。
- 懒汉式(线程安全)
public class Singleton {
// 类自身保存的唯一实例 private
private static Singleton singleton;
// 构造方法私有化
private Singleton(){
}
public static synchronized Singleton getInstance() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
这种方式在多线程下也可以正常使用,但是每次调用getInstance() 获取实例时都需要同步,造成不必要的资源开销。
- 饿汉式
public class Singleton {
// 类自身保存的唯一实例 private
private static Singleton singleton = new Singleton();
// 构造方法私有化
private Singleton(){
}
public static Singleton getInstance() {
return singleton;
}
}
这种方式基于类加载机制避免了多线程的同步问题,但在类加载时就实例化对象,提前占用了系统资源。
- 双重检查模式 (DCL)
public class Singleton {
// 类自身保存的唯一实例 private
private static Singleton singleton;
// 构造方法私有化
private Singleton(){
}
// 获取实例的静态方法
public static Singleton getInstance() {
if(singleton == null) {
synchronized (Singleton.class) {
if(singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
这里存在两次判断 singleton 是否为null,第一次判断是为了避免不必要的同步,第二次判断是仅仅在singleton== null 的时候,才创建实例。
- 静态内部类
public class Singleton {
// 构造方法私有化
private Singleton(){
}
// 静态内部类
private static class Factory {
private static final Singleton singleton = new Singleton();
}
public static Singleton getInstance() {
return Factory.singleton;
}
}
这种方式在第一次加载 Singleton 类的时候,不会进行实例化,只有在调用 getInstance() 时,虚拟机加载 Factory 类并实例化Singleton实例。不仅能保证线程安全,也可以保证只有一个 Singleton 实例,推荐使用这种方法。