2012-07-06 63 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