我想寫一個實例方法來懶惰地初始化幾個靜態變量。我初始化的對象是不可變的,對象的引用不會被類中的任何其他實例或靜態方法改變。我希望初始化代碼永遠不會被執行多次,即使在許多不同的線程中可能有多個類的實例。初始化需要在實例方法中進行,因爲該方法會覆蓋超類中的方法。我正在使用的方法如下。在多線程情況下懶惰地初始化靜態變量
private static volatile boolean isPrepared;
private static volatile Object object1;
private static volatile Object object2;
private static volatile Object object3;
@Override
void prepare() {
synchronized (this.getClass()) {
if (isPrepared) { return; }
object1 = expensiveCalculation1();
object2 = expensiveCalculation2();
object3 = expensiveCalculation3();
isPrepared = true;
}
}
我假設從初始化發生在一個synchronized塊,那將是不可能的實例來不斷觀察isPrepared
爲true
除非object1
,object2
和object3
都是非空。我還假設它不會工作,只需聲明prepare()
爲鎖定爲this
。我的假設是正確的嗎?另外,當你想將它們視爲一起初始化時,是否有一個標記爲volatile
的變量是一個好主意,還是應該將它們組合成一個Immutable類?
感謝您的回答。我想我會使用將變量綁定到單個易變變量的方法。但是,是不是volatile和synchronized block的組合是完全消除你提到的重複的可能性的最簡單方法? – 2014-11-25 12:40:09
是的。首先檢查volatile var的值,然後根據需要輸入synchronized塊。 – 2014-11-25 12:49:35
好點。如果var已經存在,你不想等待其他線程。您是否需要檢查volatile var的值兩次,一次查看是否需要同步塊,以及一次是否在塊的開頭?由於初始檢查不同步,因此在進入同步塊時,初始化可能已在另一個線程中完成。 – 2014-11-25 13:00:46