反面单例
反面單例
代碼
import java.util.ArrayList;
import java.util.List;
/**
* @since : 2023/11/17
**/
public class StupidSingleton {
private static final StupidSingleton instance = new StupidSingleton();
private static List<String> list = null;
private static Object object = null;
private StupidSingleton() {
list = new ArrayList<>();
object = new Object();
}
public synchronized static StupidSingleton getInstance() {
if (object == null) {
object = new Object();
}
return instance;
}
public void doSomething() {
list.add("Stupid");
}
}
問題點(diǎn)解析
doSomething拋出空指針異常
Java中字段、代碼塊、構(gòu)造函數(shù)初始化順序是:
- 按照在代碼中的定義順序依次加載static變量和static代碼塊。
- 按照在代碼中的定義順序依次加載實(shí)例變量和實(shí)例代碼塊。
- 構(gòu)造函數(shù)。
代入這段代碼中順序?yàn)?
- 初始化instance = new StupidSingleton()
- 執(zhí)行構(gòu)造函數(shù)
- 初始化list = null
- 初始化object = null
雖然result和object都在構(gòu)造函數(shù)中初始化了,但是隨后又被賦值為null。
多線程下效率低
估計(jì)后來的修改者發(fā)現(xiàn)了object為空的問題,所以在getInstance中又做了初始化,這樣一來,多線程下就有問題,在getInstance上加個(gè)synchronized就好了。
getInstance是static的,這個(gè)時(shí)候配合synchronized鎖的就是StupidSingleton.class,多線程下效率必然低。
修改方案
- 把instance的初始化放在所有static變量定義的最后或者在靜態(tài)變量定義時(shí)直接初始化,不在構(gòu)造函數(shù)中初始化。
- 刪除getInstance的synchronized。
- 刪除getInstance中對(duì)object的控制判斷和初始化。
總結(jié)
- 上一篇: 探索人工智能的世界:构建智能问答系统之实
- 下一篇: es笔记七之聚合操作之桶聚合和矩阵聚合