2012-07-06 62 views
56

我有一個預先填充的數組列表。我有多個線程將從數組列表中刪除元素。每個線程調用下面的remove方法並從列表中刪除一個項目。以下代碼是否給我一致的行爲?Java同步列表

ArrayList<String> list = Collections.synchronizedList(new ArrayList<String>()); 

void remove(String item) 
{ 
    do something; (doesn't work on the list) 
    list.remove(item); 
} 

謝謝!

回答

52

是的,如果您也遍歷列表,請小心,因爲在這種情況下,您需要同步它。從Javadoc

當務之急是用戶迭代它時,返回的列表上手動同步:

List list = Collections.synchronizedList(new ArrayList()); 
    ... 
synchronized (list) { 
    Iterator i = list.iterator(); // Must be in synchronized block 
    while (i.hasNext()) 
     foo(i.next()); 
} 

或者,你可以使用CopyOnWriteArrayList這對於寫入速度較慢,但​​沒有按」沒有這個問題。

+0

我對線程安全[這裏](https://stackoverflow.com/questions/46997971/concurrently-reading-a-map-while-a-single-background-thread-regularly-modifies問題-i)所以想看看你能幫助我嗎? – john 2017-10-30 00:24:17

+0

偉大的提示'CopyOnWriteArrayList'。謝謝! – FrVaBe 2018-02-23 09:51:57

23

只要你不需要「去除」方法是原子的,那應該沒問題。

換句話說,如果「做某事」檢查該項目在列表中多次出現,例如,在到達下一行時,檢查結果可能是錯誤的。

此外,迭代時請務必在名單上同步:

synchronized(list) { 
    for (Object o : list) {} 
} 

正如彼得Lawrey提到,CopyOnWriteArrayList可以讓你的生活更輕鬆,並能在高併發環境下提供更好的性能。

10

Collections#synchronizedList(List)的javadoc

返回由指定 列表支持的同步(線程安全的)列表。爲了保證串行訪問,通過返回的列表來完成對後備列表的訪問是非常重要的。當迭代時,用戶必須在返回的列表上手動進行同步。不遵循此建議可能會導致非確定性行爲。

0

它會給添加/刪除操作提供一致的行爲。但是在迭代時,你必須明確同步。 Refer this link

0

是的,它會正常工作,因爲你有​​的名單。我建議你使用CopyOnWriteArrayList

CopyOnWriteArrayList<String> cpList=new CopyOnWriteArrayList<String>(new ArrayList<String>()); 

    void remove(String item) 
    { 
     do something; (doesn't work on the list) 
       cpList..remove(item); 
    } 
1

你可以有2個diffent問題列表:
1)如果一個迭代中做了修改,即使在單線程環境中,你將有ConcurrentModificationException的像,如下例所示:

List<String> list = new ArrayList<String>(); 
for (int i=0;i<5;i++) 
    list.add("Hello "+i); 

for(String msg:list) 
    list.remove(msg); 

所以,爲了避免這個問題,你可以這樣做:

for(int i=list.size()-1;i>=0;i--) 
    list.remove(i); 

2)第二個問題可能是多線程環境。如上所述,您可以使用synchronized(list)來避免異常。

-3
synchronized(list) { 
    for (Object o : list) {} 
} 
+10

總是嘗試添加一些相關的描述到你的答案。 – 2014-05-22 08:09:43

+1

你能擴展你的答案來包含你的代碼的解釋嗎?它比讀者想象的更能幫助讀者。 – gunr2171 2014-09-30 15:41:41