结合JDK源码学习单例模式

本文JDK源码基于JDK17

饿汉式

使用staticfinal修饰实例变量,线程安全。但是可以被反射和反序列化破坏,以及如果一直不用会浪费内存。

基本实现

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/
作者
loststar
发布于
2021年12月25日
许可协议