懒汉式,线程不安全
是否 Lazy 初始化: 是
是否多线程安全: 否
实现难度: 容易
该方式最大的问题就是不支持多线程
1 | public class Singleton { |
懒汉式
是否 Lazy 初始化: 是
是否多线程安全: 是
实现难度: 容易
该方式最大的问题是效率低,因为加锁仅仅只是对第一调用起效,99% 情况下实际不需要同步
1 | public class Singleton { |
饿汉式
是否 Lazy 初始化: 否
是否多线程安全: 是
实现难度: 容易
该方式最大的问题是类加载时就初始化,浪费内存
1 | public class Singleton { |
双重校验锁
JDK 版本: JDK 1.5+
是否 Lazy 初始化: 是
是否多线程安全: 是
实现难度: 一般
该方式最大的问题是需要 JDK 1.5 及 JDK 1.5 以后
1 | public class Singleton { |
登记式/静态内部类
是否 Lazy 初始化: 是
是否多线程安全: 是
实现难度: 一般
1 | public class Singleton { |
该方式和 饿汉式 不同之处是支持 Lazy 初始化的,只有当第一次被调用时才会初始化
枚举
JDK 版本: JDK 1.5+
是否 Lazy 初始化: 否
是否多线程安全: 是
实现难度: 容易
该方式是 Effective Java 作者 Josh Bloch 推荐的方式,是实现单例模式最佳的方式。简洁,自动支持序列化机制,绝对防止多次实例化。最大的问题是需要 JDK 1.5 及 JDK 1.5 以后
1 | public enum Singleton { |
总结
一般情况下,不建议使用第 1 种和第 2 种懒汉方式,建议使用第 3 种饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用第 5 种登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式。