结合JDK源码学习单例模式
本文JDK源码基于JDK17
饿汉式
使用static
和final
修饰实例变量,线程安全。但是可以被反射和反序列化破坏,以及如果一直不用会浪费内存。
基本实现
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
//关键:构造方法私有
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
public static void otherMethod() {}
}
JDK中的饿汉式单例模式
// java.lang.Runtime
public class Runtime {
private static final Runtime currentRuntime = new Runtime();
public static Runtime getRuntime() {
return currentRuntime;
}
......
}
枚举
简单,可以避免被反射和反序列化破坏。可以通过Singleton.INSTANCE
直接调用。
基本实现
enum Singleton {
INSTANCE;
public static void otherMethod() {
}
}
JDK中的枚举单例模式
// java.util.Comparators$NaturalOrderComparator
enum NaturalOrderComparator implements Comparator<Comparable<Object>> {
INSTANCE;
......
}
双重检测锁(DCL)懒汉式
两次检查保证只调用一次创建对象的方法,提高了效率。
基本实现
public class Singleton {
// 必须加volatile,防止指令重排序
private static volatile Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
// 第一次检查
if (INSTANCE == null) {
synchronized (Singleton.class) {
// 第二次检查
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
public void otherMethod() {}
}
JDK中的DCL单例模式
// java.lang.System
public final class System {
......
private static volatile Console cons;
public static Console console() {
Console c;
if ((c = cons) == null) {
synchronized (System.class) {
if ((c = cons) == null) {
cons = c = SharedSecrets.getJavaIOAccess().console();
}
}
}
return c;
}
......
}
静态内部类
基本实现
利用jvm底层的类装载机制保证线程安全。
public class Singleton {
private Singleton() {}
private static class InnerClass {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return InnerClass.INSTANCE;
}
public static void otherMethod() {}
}
JDK中的静态内部类单例模式
// java.util.Collections
public class Collections {
......
private static class EmptyNavigableSet<E> extends UnmodifiableNavigableSet<E> implements Serializable {
......
private static final NavigableSet<?> EMPTY_NAVIGABLE_SET = new EmptyNavigableSet<>();
......
}
public static <E> SortedSet<E> emptySortedSet() {
return (SortedSet<E>) UnmodifiableNavigableSet.EMPTY_NAVIGABLE_SET;
}
}
不推荐使用的实现方式
线程不安全的懒汉式
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
public void otherMethod() {}
}
使用同步方法的懒汉式
效率非常低。
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {}
// 在方法上加synchronized
public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
public void otherMethod() {}
}
单检测锁懒汉式
线程不安全。
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null) {
synchronized (Singleton.class) {
INSTANCE = new Singleton();
}
}
return INSTANCE;
}
public void otherMethod() {}
}
参考
结合JDK源码学习单例模式
https://blog.loststar.tech/posts/ff220a60/