单例模式
- 适用于消耗资源过多的对象
- 构造函数为private
- 通过一个静态方法或枚举返回单例类的对象
- 确保单例类的对象只有一个
饿汉单例模式
public class A{
private static final A a = new A();
private A(){}
public static A getInstance(){
return a;
}
}
懒汉模式
public class A{
private static final A a;
private A(){}
public static synchronized A getInstance(){
if(a == null){
a = new A();
}
}
}
- 能够保证在多线程情况下单例对象的唯一性,但是第一次加载的时候需要及时的实例化,反应稍慢,而且每次调用方法的时候都会进行同步synchronized,造成不必要的开销。
Double Check Lock(DCL模式)
- 既能够在需要的时候才开始实例化,又能保证线程安全,而且对象初始化后再次调用不进行同步锁。
public class A{
private static A a = null;
private A(){}
public static A getInstance(){
if (a == null){
synchronized(A.class){
if(a == null){
a = new A();
}
}
}
return a;
}
}
静态内部类单例模式
- DCL 模式在某些情况下会出现失效的问题,称双重检查锁定(DCL)失效。使用静态内部类,能够保证线程安全,也能保证线程对象的唯一性,同时也延时加载了单例的实例化。推荐使用。
public class A{
private A(){}
public static A getInstance(){
return AHolder.instance;
}
private static class AHolder{
private static final A instance = new A();
}
}
枚举单例
public enum A{
INSTANCE;
public void doSomething(){
System.out.println("");
}
}
- 默认枚举实例的创建是线程安全的,并且在任何情况下它都是一个单例。
- 以上的单例模式,在反序列化的时候都可能会出现,重新创建对象的情况,需要加入以下的方法
private Object readResolve() throws ObjectStreamException{
return instance;
}
使用容器实现单例模式
public class A{
private static Map<String,Object> objectMap = new HashMap<String,Object>();
private A(){}
public static void registerService(String key,Object instance){
if(!objectMap.containsKey(key)){
objectMap.put(key,instance);
}
}
public static Object getService(String key){
return objectMap.get(key);
}
}