正确写出Java的单例模式

单例模式是Java中最常见也是面试经常被问到的一种设计模式,本文详细列出了单例模式的几种写法。

懒汉式,双重校验锁

双重校验,多个线程下调用,只会创建一个实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Singleton {

private static Singleton instance;

private Singleton() {
}

public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();

}
}
}
return instance;
}
}

饿汉式,线程安全

这种方法非常简单,实例被声明为final+static,第一次类加载到内存中就被初始化了,因此线程是安全的。
但种方法也是有缺点的,它不是一种懒加载模式,单例会在加载类后一开始就被初始化,即使客户端没有调用 getInstance()方法,所以它是典型的空间换时间,比较占内存。特别是一些需要依赖参数实例的,无法使用此方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Singleton {

private static final Singleton instance = new Singleton();

private Singleton() {
}

public static Singleton getInstance() {

return instance;
}
}

静态内部类

这种写法仍然使用JVM本身机制保证了线程安全问题;由于 InnerSingleton是私有的,除了 getInstance() 之外没有办法访问它,因此它是懒汉式的.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Singleton {

private static class InnerSingleton {
private static final Singleton INSTANCE = new Singleton();
}

private Singleton() {
}

public static Singleton getInstance() {

return InnerSingleton.INSTANCE;
}
}

枚举

这种方法可以说是最简单的了。我们可以通过Singleton.INSTANCE访问实例,同时枚举是默认线程安全的。

1
2
3
public enum Singleton {
INSTANCE;
}

总结

一般情况下推荐饿汉式和静态内部类这两种写法。

Read More