单例模式概念
保证了内存中只有一个对象
饿汉式
一上来就加载对象
有可能会浪费内存
//饿汉式单例
public class Hungry {
//可能会浪费空间
private byte[] a1 = new byte[1024*1024];
private byte[] a2 = new byte[1024*1024];
private byte[] a3 = new byte[1024*1024];
private byte[] a4 = new byte[1024*1024];
private Hungry(){
}
private final static Hungry HUNGRY = new Hungry();
private static Hungry getInstance(){
return HUNGRY;
}
}
懒汉式
要用的时候才回去加载
懒汉式单线程模式
这种情况多线程会出问题,所以只适合单线程
//懒汉式单例
public class Lazy {
private Lazy(){
}
private static Lazy lazy;
private static Lazy getInstance(){
if (lazy == null){
lazy = new Lazy();
}
return lazy;
}
}
DCL懒汉式(多线程双重锁模式)
public class Lazy2 {
private Lazy2(){
System.out.println(Thread.currentThread().getName() + "ok");
}
private static Lazy2 lazy2;
private static Lazy2 getInstance(){
//双重检测模式 懒汉式单例 DCL
if (lazy2 == null){
synchronized (Lazy2.class){
if (lazy2 == null){
lazy2 = new Lazy2();
}
}
}
return lazy2;
}
public static void main(String[] args) {
new Thread(()->{
for (int i = 0; i < 10; i++) {
Lazy2.getInstance();
}
}).start();
}
}
但是 lazy2 = new Lazy2(); 不是一个原子性操作
.
会产生三个步骤而这三个步骤会导致指令重排
1.分配内存空间
2、执行构造方法,初始化对象
3、把这个对象指向这个空间
.
所以需要给定义的变量加volatile
即 private volatile static Lazy2 lazy2;