标签:方法 初始 多个实例 image 构造方法 java ++ art ima
总之就是构造器私有化,提供一个公共的方法创建实例供外部使用。
//饿汉式单例
public class Hungry {
//可能会造成空间的浪费,因为一开始就将这个对象new出来了
private Hungry(){
}
private final static Hungry HUNGRY = new Hungry();
public static Hungry getInstance(){
return HUNGRY;
}
}
//懒汉式
public class Lazy {
private Lazy() {
}
private static Lazy lazy;
public static Lazy getInstance() {
if (lazy == null) {
lazy = new Lazy();
}
return lazy;
}
问题
:多线程下会出问题
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
new Thread(() -> {
Lazy.getInstance();
}
).start();
}
}
/**
多线程下执行创建了多个实例
-----------------------
Thread-0 Ok
Thread-1 Ok
-----------------------
*/
//DCL双重检测锁
public class DCL {
private DCL(){
}
/*加上volatile禁止指令重排,因为下面dcl = new DCL()这个动作不是原子性的,
分为三步:1.分配内存空间。2.执行构造方法初始化对象。3.将这个对象指向这个内存空间。
2和3的执行顺序可能被交换,多线程就有可能造成空指针的异常。
*
*/
private volatile static DCL dcl;
public static DCL getInstance(){
//通过双重检测
if(dcl== null){
//需要锁这个类
synchronized (DCL.class){
if (dcl == null){
dcl = new DCL();
}
}
}
return dcl;
}
多线程下安全,但是能被反射破坏。
//静态内部类内部类单例
public class Inner {
private Inner(){}
public static Inner getInstance(){
return InnerClass.INNER;
}
public static class InnerClass{
private final static Inner INNER = new Inner();
}
}
以上方式创建的单例都能够被反射破坏
//枚举单例
public enum ESingle{
INSTANCE;
public ESingle getInstance(){
return INSTANCE;
}
}
安全
因为不能通过反射来进行实例化。
标签:方法 初始 多个实例 image 构造方法 java ++ art ima
原文地址:https://www.cnblogs.com/Mr-hanexp/p/12992732.html