雙重檢查鎖
package com.fh.design_mode.singleton.double_check_lock;
import lombok.SneakyThrows;
import java.util.concurrent.TimeUnit;
/**
* 雙重檢查鎖
*/
public class SingletonTest {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "例物件=" + Singleton.getInstance());
}, "執行緒" + i).start();
}
}
}
class Singleton {
private static volatile Singleton instance = null;//volatile 禁止重排序
private Singleton() {
}
@SneakyThrows
public static Singleton getInstance() {
if (instance == null) {//效率
synchronized (Singleton.class) {
System.out.println("【debug】" + Thread.currentThread().getName() + "獲得物件鎖");
TimeUnit.SECONDS.sleep(2);
if (instance == null) {//物件是否為空
/*
①分配棧空間=》②分配堆記憶體=》③棧指標指向堆記憶體
因為重排序最佳化的存在
執行緒A①③棧指標指向堆記憶體,例項分配記憶體後就不是null。
執行緒B進入判斷instance!=null,直接返回A執行緒建立的不完整的例項。
*/
instance = new Singleton();
}
System.out.println("【debug】" + Thread.currentThread().getName() + "釋放物件鎖。。。");
}
}
return instance;
}
}
靜態內部類
package com.fh.design_mode.singleton.static_inner_class;
import lombok.SneakyThrows;
import java.util.concurrent.TimeUnit;
/**
* 靜態內部類
*/
public class SingletonTest {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
Singleton.SingletonHolder a = new Singleton.SingletonHolder();
System.out.println(Singleton.getInstance());
}).start();
}
}
}
class Singleton {
private Singleton() {
}
static class SingletonHolder {
//虛擬機器會保證一個類的 <clinit>() 方法在多執行緒環境中能被正確的加鎖、同步。
private static Singleton INSTANCE = new Singleton();
}
@SneakyThrows
public static Singleton getInstance() {
TimeUnit.SECONDS.sleep(3);
return SingletonHolder.INSTANCE;
}
}
餓漢式
package com.fh.design_mode.singleton.hungry_lock;
import lombok.SneakyThrows;
import java.util.concurrent.TimeUnit;
/*
*餓漢式
* */
public class SingletonTest {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
System.out.println(Sinleton.getInstance());
}).start();
}
}
}
class Sinleton {
private static final Sinleton instance = new Sinleton();
private Sinleton() {
}
@SneakyThrows
public static Sinleton getInstance() {
TimeUnit.SECONDS.sleep(2);
return instance;
}
}