单例模式
大约 2 分钟
特征
- 创建私有构造函数以避免使用 new 操作实例化对象
- 声明一个类的「私有」、「静态」实例
- 提供一个「公共静态方法」,该方法将返回单例类的实例变量。
适用场景
- 当希望类只能有一个实例时。
- 需要维护某种全局状态时。
- 控制对共享资源的并发访问。
✨饿汉实例化
public class EagerInitializedSingleton {
private static final EagerInitializedSingleton instance = new EagerInitializedSingleton();
private EagerInitializedSingleton(){}
public static EagerInitializedSingleton getInstance() {
return instance;
}
}
- 实例在类加载时创建。
- 缺点是不使用该类时,也会创建实例对象
静态代码块实例化
public class StaticBlockSingleton {
private static StaticBlockSingleton instance;
private StaticBlockSingleton(){}
static {
try {
instance = new StaticBlockSingleton();
} catch (Exception e) {
//...
}
}
public static StaticBlockSingleton getInstance() {
return instance;
}
}
- 类的实例对象在
try..catch
语句块创建
懒汉实例化
public class LazyInitializedSingleton {
private static LazyInitializedSingleton instance;
private LazyInitializedSingleton(){}
public static LazyInitializedSingleton getInstance() {
if (instance == null) {
instance = new LazyInitializedSingleton();
}
return instance;
}
}
- 在需要的时候,在进行实例化
- 缺点是:多个线程同时处于
if
语句时,容易出现实例化多个对象的情况
线程安全-synchronized 关键字
public class ThreadSafeSingleton {
private static ThreadSafeSingleton instance;
private ThreadSafeSingleton(){}
public static synchronized ThreadSafeSingleton getInstance() {
if (instance == null) {
instance = new ThreadSafeSingleton();
}
return instance;
}
}
- 线程安全,每次只有一个线程进入
getInstance()
方法。 - 同步方法会造成性能降低
✨双重锁
package com.journaldev.singleton;
public class ThreadSafeSingleton {
private static ThreadSafeSingleton instance;
private ThreadSafeSingleton(){}
public static ThreadSafeSingleton getInstanceUsingDoubleLocking() {
if (instance == null) {
synchronized (ThreadSafeSingleton.class) {
if (instance == null) {
instance = new ThreadSafeSingleton();
}
}
}
return instance;
}
}
- 双重检查锁: if 内部使用同步代码块,并增加额外一个检查。
✨私有内部类
public class BillPughSingleton {
private BillPughSingleton(){}
private static class SingletonHelper {
private static final BillPughSingleton INSTANCE = new BillPughSingleton();
}
public static BillPughSingleton getInstance() {
return SingletonHelper.INSTANCE;
}
}
- 当
BillPughSingleton
加载时,私有静态内部类SingletonHelper
不会被加载到内存中 - 当调用
getInstance()
时,内部类才会被加载并且实例化单例类。
枚举类
public enum EnumSingleton {
INSTANCE;
public static void doSomething() {
// do something
}
}