如果線程在安全出版物之後從未修改過,則可以共享線程之間的任何對象或數據結構。如註釋中所述,在初始化ArrayList
的寫入和其他線程獲取引用的讀取之間必須存在* happen-before *關係。
E.g.如果在啓動其他線程之前或在將列表中的任務提交到ExecutorService
之前完全設置了ArrayList
,則表明您是安全的。
如果線程已經運行,則必須使用其中一個線程安全機制將ArrayList
引用移交給其他線程,例如,通過把它放在BlockingQueue
。
即使是最簡單的形式,如將參考文件存儲到static final
或volatile
字段也可以使用。
請記住,以後不要修改對象的前提條件必須始終成立。我們建議使用Collections.unmodifiableList(…)
包裝清單執行這一約束,忘了原來的列表引用發佈前:
class Example {
public static final List<String> THREAD_SAFE_LIST;
static {
ArrayList<String> list=new ArrayList<>();
// do the setup
THREAD_SAFE_LIST=Collections.unmodifiableList(list);
}
}
或
class Example {
public static final List<String> THREAD_SAFE_LIST
=Collections.unmodifiableList(Arrays.asList("foo", "bar"));
}
如果對象不可能有來自不同線程的狀態變化,那麼問題是什麼?也許我讀錯了這個問題,但它似乎是一個明智之舉。唯一的問題可能是如果任何ArrayList元素的狀態可以改變。我不會將列表傳遞給其他對象,而是將列表的深層副本或類的對象完全封裝並保護列表。 –
是的,你可以。嘗試一下。 –
您可能仍然需要某種同步來確保初始化列表的寫操作發生在讀操作之前,其中*發生之前*指的是[JLS中定義的概念](http://docs.oracle.com)。 com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5),否則可能會遇到緩存一致性或指令重新排序的問題,導致其他線程看到部分構建的列表。 – user2357112