单例模式的概念
单例模式是指确保一个类只有一个唯一实例,并且提供一个全局的访问点。
单例模式的设计思路
- 为了防止其他类利用构造方法创建多个对象,将构造方法声明为private
类型。 - 对外提供一个静态方法getInstance()来获取实例对象。同时应该保证无论getInstance()方法被调用多少次,得到的始终是一个对象。
单例模式的实现方式
- 饿汉模式
优点:实现简单,线程安全,不用加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。
public class Singleton {
// 静态成员变量
private static Singleton instance = new Singleton();
// 当类的构造函数为私有时,只能在本类实例化该类的对象。
private Singleton(){
}
// 提供一个公共的静态方法返回单一实例
public static Singleton getInstance(){
return instance;
}
}
- 懒汉模式
优点: lazy loading延时加载,第一次调用才初始化,避免内存浪费。
缺点:线程不安全,在多线程环境下不能正常工作。严格意义上不能算一种单例模式实现
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 懒汉模式 (线程安全)
优点: lazy loading延时加载,第一次调用才初始化,避免内存浪费。
缺点:加锁 synchronized 才能保证单例,影响工作效率
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 懒汉模式 (双检锁/双重校验锁(DCL,即 double-checked locking))
优点: lazy loading延时加载,第一次调用才初始化,避免内存浪费。安全且在多线程情况下能保持高性能
public class Singleton {
private volatile static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return instance;
}
}
- 静态内部类
优点: lazy loading延时加载,第一次调用才初始化,避免内存浪费。线程安全。
public class Singleton {
private Singleton (){}
// 静态内部类
private static class SingletonHolder (){
public static final Singleton INSTANCE = new Singleton();
}
// Singleton 类被装载了,instance 不一定被初始化。因为 SingletonHolder 类没有被主动使用,只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance。
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
- 枚举
优点: 这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。
这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。
public enum Singleton {
INSTANCE;
}