单例模式java

静态方法

1
2
3
4
5
6
7
8
9
10
11
// 这种方法,多线程下会有并发问题
public class SingletonDemo {
private static SingletonDemo instance = null;
private SingletonDemo() {}
public static synchronized SingletonDemo getInstance() {
if (instance == null) {
instance = new SingletonDemo();
}
return instance;
}
}

加上内置锁

1
2
3
4
5
6
7
8
9
10
11
12
13
// 这种方法的问题在于每次都需要同步,非常耗性能
public class SingletonDemo {
private static SingletonDemo instance = null;
private SingletonDemo() {}
public static synchronized SingletonDemo getInstance() {
synchronized (SingletonDemo.class) {
if (instance == null) {
instance = new SingletonDemo();
}
}
return instance;
}
}

再加一层null判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 这种就是最典型的double-check单例
// double-check依然存在一个问题,sync内置锁只保证了原子性和可见性,new操作会出现指令重排问题,当线程1出现先引用分配了内存时,线程2检查发现对象不为空,但此时线程1还没创建完对象,线程2拿到的是一个空对象返回处理了,会导致空异常。
public class SingletonDemo {
private static SingletonDemo instance = null;
private SingletonDemo() {}
public static synchronized SingletonDemo getInstance() {
if (instance == null) {
synchronized (SingletonDemo.class) {
if (instance == null) {
instance = new SingletonDemo();
}
}
}
return instance;
}
}

加volatile关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// volatile 可以禁止指令重排
// 缺点,太复杂了
public class SingletonDemo {
private volatile static SingletonDemo instance = null;
private SingletonDemo() {}
public static synchronized SingletonDemo getInstance() {
if (instance == null) {
synchronized (SingletonDemo.class) {
if (instance == null) {
instance = new SingletonDemo();
}
}
}
return instance;
}
}

类加载时就初始化

1
2
3
4
5
6
7
8
9
// 类加载时初始化就没有上面同步的问题
// 但这个私有构造函数可以通过反射序列化可以被调用,破坏了单例性
public class SingletonDemo {
private static SingletonDemo instance = new SingletonDemo();
private SingletonDemo() {}
public static synchronized SingletonDemo getInstance() {
return instance;
}
}

控制反射序列化情况

1
2
3
4
5
6
7
8
9
10
11
// 添加readResolve方法防止反射问题
public class SingletonDemo {
private static SingletonDemo instance = new SingletonDemo();
private SingletonDemo() {}
public static synchronized SingletonDemo getInstance() {
return instance;
}
private Object readResolve() throws ObjectStreamException {
return instance;
}
}

静态内部类

1
2
3
4
5
6
7
8
9
10
// 现在使用最为普遍的一种方式,清晰简单
public class SingletonDemo {
private SingletonDemo() {}
private static class Holder {
private static SingletonDemo instance = new SingletonDemo();
}
public static SingletonDemo getInstance() {
return Holder.instance;
}
}

枚举类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 单元素的枚举类型已经成为实现Singleton的最佳方法
// enum中的实例被保证只会被实例化一次
enum SingletonEnum {
RESOURCE;
private Resource instance;
SingletonEnum() {
instance = new Resource();
}
public Resource getInstance() {
return instance;
}
}
class Resource {
}
public class Test {
public static void main(String[] args) {
SingletonEnum.RESOURCE.getInstance();
}
}