饿汉:吃饱再说
优点:绝对的线程安全(在线程访问前就已经初始化了),逻辑简单,可读性好
缺点:如果对象被大量使用的话,导致内存开销增加,反射,克隆可破坏
public class HungrySimpleton{
private static final HungrySimpleton hungrysimpleleton = new HungrySimpleton();
private HungrySimpleton(){}
public static HungrySimpleton getInstance() { return hungrysimpleleton;}
}
//改进
public class HungrySimpleton{
private static final HungrySimpleton hungrysimpleleton;
static {
hungrysimpleleton = new HungrySimpleton();
}
private HungrySimpleton(){}
public static HungrySimpleton getInstance() { return hungrysimpleleton;}
}
spring ioc
懒汉:要用的时候再吃
优点:资源占用少,逻辑简单
缺点:线程不安全
public class LazySimpleSingleton {
private static LazySimpleSingleton lss = null;
private LazySimpleSingleton(){};
public static LazySimpleSingleton getInstance(){
if(null == lss){
lss = new LazySimpleSingleton();
}
return lss;
}
}
解决办法:加上锁 ,但效率低,线程阻塞
public synchronized static LazySimpleSingleton getInstance(){
if(null == lss){
lss = new LazySimpleSingleton();
}
return lss;
}
双重校验锁:
public class LazyDoubleCheckSingleton {
private volatile static LazyDoubleCheckSingleton ldcs= null;
private LazyDoubleCheckSingleton(){};
public static LazyDoubleCheckSingleton getInstance(){
if(null == ldcs) {//控制第二次访问不在拥堵
synchronized (LazyDoubleCheckSingleton.class) {
if (null == ldcs ) {//控制
ldcs = new LazyDoubleCheckSingleton();
//多线程情况下会出现cpu指令重排序
}
}
}
return ldcs;
}
}
静态内部类:先静态后动态,先属性后方法
优点:代码优雅,可读性好,线程安全
缺点:在反射的情况下会破坏单例
public class LazyStaticInnerClassSingleton {
private LazyStaticInnerClassSingleton (){}
public static LazyStaticInnerClassSingleton getInstance(){
return LazyHolder.INSTANCE;
}
private static final class LazyHolder{
private static final LazyStaticInnerClassSingleton INSTANCE =
new LazyStaticInnerClassSingleton();
}
}
如何解决呢?
方案一:在构造方法抛出异常(这里就类似下面枚举的解决方法,只不过没那么优雅)
public class LazyStaticInnerClassSingleton {
private LazyStaticInnerClassSingleton (){
if(null != LazyHolder.INSTANCE){
throw new RuntimeException("不允许使用非法手段创建单例对象");
}
}
public static LazyStaticInnerClassSingleton getInstance(){
return LazyHolder.INSTANCE;
}
private static final class LazyHolder{
private static final LazyStaticInnerClassSingleton INSTANCE =
new LazyStaticInnerClassSingleton();
}
}
方案二:注册式单例:枚举类
Spring IOC 容器 原型 --> lazy加载
public enum EnumSingleton {
INSTANCE;
private Object data;
public Object getData() {return data;}
public void setData(Object data){ this.data = data; }
public static EnumSingleton getInstance(){return INSTANCE;}
}
还在学习中…