Java23种设计模式之单例模式
第一种(饿汉)
//饿汉试
class Singleton01 {
private Singleton01() {
}
private static Singleton01 singleton = new Singleton01();
public static Singleton01 getSingleton() {
return singleton;
}
}
这种方式基于classloder机制避免了多线程的同步问题,不过,singleton在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getSingleton方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化singleton显然没有达到lazy loading的效果。
第二种(饿汉)
class Singleton02 {
private Singleton02() {
}
private static Singleton02 singleton = null;
static {
singleton = new Singleton02();
}
public static Singleton02 getSingleton() {
return singleton;
}
}
表面上看起来差别挺大,其实更第一种方式差不多,都是在类初始化即实例化singleton。
第三种(懒汉)
class Singleton03 {
private Singleton03() {
}
private static Singleton03 singleton03;
public static Singleton03 getSingleton() {
if (singleton03 == null)
singleton03 = new Singleton03();
return singleton03;
}
}
这种写法lazy loading很明显,但是缺点的是在多线程不能正常工作。
第四种(懒汉 线程安全 不推荐)
class Singleton04 {
private Singleton04() {
}
private static Singleton04 singleton04;
public static synchronized Singleton04 getSingleton() {
if (singleton04 == null)
singleton04 = new Singleton04();
return singleton04;
}
}
这种写法解决了第三种的的缺点,但是在效率上大打折扣,99%的几率都会去同步
第五种(懒汉 双重检查 线程安全 推荐)
class Singleton05 {
private Singleton05() {
}
// volatile可以保证即使java虚拟机对代码执行了指令重排序,也会保证它的正确性。
private static volatile Singleton05 singleton05;
public static Singleton05 getSingleton() {
if (singleton05 == null)
synchronized (Singleton05.class) {
if (singleton05 == null) {
singleton05 = new Singleton05();
}
}
return singleton05;
}
}
这种写法解决了第四种的缺点,用两次判断来解决每次需要同步的问题.虽然使用了volatile 降低了效率,但是也无伤大雅.
第六种(静态内部类 线程安全 推荐)
class Singleton06 {
private Singleton06() {
}
static class Singletons {
private final static Singleton06 singleton06 = new Singleton06();
}
public static Singleton06 getSingleton() {
return Singletons.singleton06;
}
}
这种方式同样利用了classloder的机制来保证初始化Singleton06 时只有一个线程,Singleton06 类被装载了,singleton06不一定被初始化。因为Singletons 类没有被主动使用,只有显示通过调用getSingleton方法时,才会显示装载Singletons 类,从而实例化singleton06 。
第七种(枚举 线程安全 推荐)
enum Singleton07 {
SINGLETON;
public static Singleton07 getSingleton() {
return SINGLETON;
}
}
这种方式是Effective Java作者Josh Bloch 提倡的方式,最佳的单例实现模式就是枚举模式。利用枚举的特性,让JVM来帮我们保证线程安全和单一实例的问题,而且还能防止反序列化重新创建新的对象。除此之外,写法还特别简单。