单例创建的三种方式
- 饿汉式
/**
* @author WangJie
* @version 1.0
* @Description:单例模式——饿汉模式
* @date: 2020/6/8 20:58
* @since JDK 1.8
*/
// 属性和方法都是静态的,会提前加载,如不使用会浪费空间
public class Hungry {
// 构造器私有
private Hungry(){}
private static final Hungry HUNGRY = new Hungry();
public static Hungry getInstance(){
return HUNGRY;
}
}
- 懒汉式
/**
* @author WangJie
* @version 1.0
* @Description:单例模式——懒汉模式
* @date: 2020/6/8 21:05
* @since JDK 1.8
*/
public class LazyMan {
private LazyMan() {}
private volatile static LazyMan lazyMan;
public static LazyMan getInstance(){
if (lazyMan == null) {
lazyMan = new LazyMan();
}
return lazyMan;
}
}
-
注意! 多线程并发的情况下,懒汉模式并不安全!
-
怎么解决呢? 加锁!
-
再注意:lazyMan = new LazyMan();并不是原子性操作
-
静态内部类实现单例
/**
* @author WangJie
* @version 1.0
* @Description:单例模式——静态内部类
* @date: 2020/6/8 21:31
* @since JDK 1.8
*/
public class Holder {
private Holder(){}
public static Holder getInstance(){
return InnerClass.HOLDER;
}
private static class InnerClass{
private static final Holder HOLDER = new Holder();
}
}
最安全的懒汉模式就真的安全了吗?
- 先随便反射一下试试看:破坏失败。
- 整点高级的:破坏成功。
- 怎么防守呢?在私有的构造中加锁,三重检测。
- 但是,但是,如果两个对象都是反射生成的呢?
什么原理啊(我要再看看反射的知识。。)
- 再来一次漂亮的防守
- 又但是,还有漏洞,如果我知道了隐藏的变量名flag。。
- 道高一尺魔高一丈!!!
绝对安全的单例长什么样?
- 答案:枚举类。
/**
* @author WangJie
* @version 1.0
* @Description:枚举实现单例
* @date: 2020/6/8 22:58
* @since JDK 1.8
*/
public enum SingleEnum {
INSTANCE;
public static SingleEnum getInstance(){
return INSTANCE;
}
}
- 破解试试
- 我们来看看源码
明白了吗?