5 Ways to Implement Singleton in Java

2 minute read

常用的五种 Java 单例(Singleton)模式实现方式,结合实际情况选用

Hungry (饿汉式)

线程安全,调用效率高,不可延时加载

1public class Singleton {
2    private static Singleton instance = new Singleton;
3    private Singleton() {}
4    public static Singleton getInstance() {
5        return instance;
6    }
7}

这是单例模式中最简单的一种实现方式,但是存在非常明显的问题,单例还没有使用的时候就已经被初始化,也就是哪怕程序从头到尾都没使用这个单例,单例的对象还是会被创建,造成不必要的资源浪费

Lazy (懒汉式)

线程安全,调用效率不高,可延时加载

 1public class Singleton {
 2    private static Singleton instance;
 3    private Singleton() {}
 4    public static synchronized Singleton getInstance() {
 5        if(instance == null) {
 6            instance = new Singleton();
 7        }
 8        return instance;
 9    }
10}

类初始化时不会初始化对象实例,实现了延时加载,但是公开方法同步加载,所以调用效率低

DCL (双重锁判断机制)

DCL 即 Double-Check Lock, 由于 JVM 底层存在的问题,偶尔会出现异常,不建议使用

 1public class Singleton {
 2    private volatile static Singleton instance;
 3    private Singleton() {}
 4    public static Singleton getInstance() {
 5        if(instance == null) {
 6            synchronized (Singleton.class) {
 7                if(instance == null) {
 8                    instance = new Singleton();
 9                }
10            }
11        }
12        return instance;
13    }
14}

Static (静态内部类)

线程安全,调用效率高,可延时加载

1public class Singleton {
2    private static class SingletonInstance {
3        private static final Singleton instance = new Singleton();
4    }
5    private Singleton() {}
6    public static Singleton getInstance() {
7        return SingletonInstance.instance;
8    }
9}

enum (枚举类)

线程安全,调用效率高,不可延时加载,因其自身特性,可以天然地防止反射和反序列化调用

1public enum Singleton {
2    INSTANCE;
3    public void singletonOartion() {
4        /* your operations here... */
5    }
6}