目的:保证一个类只有一个实例,并提供一个访问他的全局访问点
关键代码:
介绍几种单例模式的实现方式 - 有种回字的几种写法的意思,略无聊
懒汉式 - 线程不安全
1 2 3 4 5 6 7 8 9 10 11
| public class Singleton01 { private static Singleton01 instance; private Singleton01(){}
public static Singleton01 getInstance() { if (instance == null) { instance = new Singleton01(); } return instance; } }
|
简单易懂,但是线程不安全
懒汉式 - 线程安全
1 2 3 4 5 6 7 8 9 10 11
| public class Singleton02 { private static Singleton02 instance; private Singleton02() {}
public static synchronized Singleton02 getInstance() { if (instance == null) { instance = new Singleton02(); } return instance; } }
|
实现简单,线程安全,方法体加锁比较耗资源,当 getInstance() 调用不频繁时可以使用
饿汉式 - 线程安全
1 2 3 4 5 6 7 8
| public class Singleton03 { private static Singleton03 instance = new Singleton03(); private Singleton03() {}
public static Singleton03 getInstance() { return instance; } }
|
实现简单,线程安全,通过 classloader 避免同步问题,缺点是类加载就初始化,浪费内存
双检锁/双重校验锁 DCL double-checked locking
注意 volatile 的使用,避免指令重排
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Singleton04 { private volatile static Singleton04 instance; private Singleton04() {}
public static Singleton04 getInstance() { if (instance == null) { synchronized (Singleton04.class) { if (instance == null) { instance = new Singleton04(); } } } return instance; } }
|
略显复杂,但是性能良好效率高,懒加载,线程安全 Java 1.5 后有效。
登记式/静态内部类
1 2 3 4 5 6 7 8 9 10
| public class Singleton05 { private static class SingletonHolder { private static final Singleton05 INSTANCE = new Singleton05(); } private Singleton05() {}
public static Singleton05 getInstance() { return SingletonHolder.INSTANCE; } }
|
实现简单,线程安全,懒加载。效果和双检锁一致。但是由于只在被使用时才通过 classloader 加载,效率回更高
枚举
1 2 3 4
| public enum Singleton06 { INSTANCE; public void whateverMethod() {} }
|
理论上来说最安全,最简单的实现,不过不流行。 Effective Java 作者推荐的写法