0%

如何实现一个好的单例模式?

单例模式在开发中会经常用到,那么如何实现一个优雅的单例就显的尤为重要.在实现的时候,我们需要根据具体情况考量如下信息:

  • 是否需要线程安全?
  • 是否需要懒加载?

这里便来介绍4种常用的单例实现:饿汉,静态内部类,双重检查锁,枚举

懒汉式

懒汉是在开发中用的最多的情况,实现简且线程安全.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* @author lazycece
*/
public class A {
private static A a = new A();

private A() {

}

public static A getInstance() {
return a;
}
}

双重检查锁

双重检查锁是一种稍微复杂的实现,其具备懒加载特性,在考虑线程安全的情况下,还需引入volatile关键字,特点如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @author lazycece
*/
public class B {
private volatile static B b = null;

private B() {

}

public static B getInstance() {
if (b == null) {
synchronized (B.class) {
if (b == null) {
b = new B();
}
}
}
return b;
}
}

## 静态内部类

静态内部类实现是懒加载且线程安全的,其的懒加载是利用了内部类不在类加载时加载而是在第一次调用时加载的特性.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @author lazycece
*/
public class C {
private C() {

}

private static class CHolder {
public static final C c = new C();
}

public static C getInstance() {
return CHolder.c;
}
}

枚举

枚举是实现单例模式的最佳方法.这种方式是 Effective Java 中提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* @author lazycece
*/
public enum D {
instance;

public void print() {
System.out.println("===");
}

public static void main(String[] args) {
D.instance.print();
}
}