网上流传很多java单例的写法,让人看了很是不解,一个简单的单例为何如此复杂,让人都不敢确定自己写的单例可不可用了。其实很多的变体都是基于线程安全考虑的,之所以觉得复杂,是未能搞清楚应用的场景。绝对的线程安全是要付出代价的,我们只要知道我们写的单例模式能满足我们的并发需求,就可以放心的使用了。
-
最简单的写法
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton() {
}
public static Singleton getSignleton() {
return singleton;
}
}
既然是单例模式,就是为了使用的时候能调用到它,迟早要创建,而且创建了也不会销毁,这点内存,可以承担。
-
延迟创建
public class Singleton {
private static Singleton singleton = null;
private Singleton() {
}
public static Singleton getSignleton() {
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
-
考虑线程安全的延迟创建
public class Singleton {
private static Singleton singleton = null;
private Singleton() {
}
public static Singleton getSignleton() {
synchronized (Singleton.class){
if (singleton == null){
singleton = new Singleton();
}
}
return singleton;
}
}
-
双重检查的延迟创建
public class Singleton {
private static Singleton singleton = null;
private Singleton() {
}
public static Singleton getSignleton() {
if (singleton == null){
synchronized (Singleton.class){
if (singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
有大量线程访问的时候,只要有一个线程执行过了,其他都能正确的拿到值,即使不做同步,而出现并发创建多个对象的场景少之又少,为了满足处女座的情节就用这种吧。
-
枚举单例模式
public class LockContainer {
private LockContainer() {
}
public static LockContainer getInstance() {
return LockContainerEnum.INSTANCE.getInstance();
}
private enum LockContainerEnum {
INSTANCE;
LockContainer container = null;
LockContainerEnum() {
container = new LockContainer();
}
private LockContainer getInstance() {
return container;
}
}
}
注意细节虽好,但不要被细节所束缚,以至于无法抉择。我喜欢用最简单的和枚举。