反面單例 代碼 import java.util.ArrayList; import java.util.List; /** * @since : 2023/11/17 **/ public class StupidSingleton { private static final StupidSin ...
反面單例
代碼
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");
}
}
問題點解析
doSomething拋出空指針異常
Java中欄位、代碼塊、構造函數初始化順序是:
- 按照在代碼中的定義順序依次載入static變數和static代碼塊。
- 按照在代碼中的定義順序依次載入實例變數和實例代碼塊。
- 構造函數。
代入這段代碼中順序為:
- 初始化instance = new StupidSingleton()
- 執行構造函數
- 初始化list = null
- 初始化object = null
雖然result和object都在構造函數中初始化了,但是隨後又被賦值為null。
多線程下效率低
估計後來的修改者發現了object為空的問題,所以在getInstance中又做了初始化,這樣一來,多線程下就有問題,在getInstance上加個synchronized就好了。
getInstance是static的,這個時候配合synchronized鎖的就是StupidSingleton.class,多線程下效率必然低。
修改方案
- 把instance的初始化放在所有static變數定義的最後或者在靜態變數定義時直接初始化,不在構造函數中初始化。
- 刪除getInstance的synchronized。
- 刪除getInstance中對object的控制判斷和初始化。
本文來自博客園,作者:U6B66,轉載請註明原文鏈接:https://www.cnblogs.com/u6b66/p/17839856.html