Java同步列表

sha*_*fax 64 java multithreading

我有一个预先填充的数组列表.我有多个线程将从数组列表中删除元素.每个线程调用下面的remove方法,并从列表中删除一个项目.以下代码是否给我一致的行为?

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

void remove(String item)
{
     do something; (doesn't work on the list)
     list.remove(item);
}
Run Code Online (Sandbox Code Playgroud)

谢谢!

Pet*_*rey 66

是的,如果您也在列表上进行迭代,请小心,因为在这种情况下,您需要对其进行同步.来自Javadoc:

当迭代它时,用户必须手动同步返回的列表:

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

或者,您可以使用CopyOnWriteArrayList哪个写入较慢但没有此问题.

  • 每当您需要同步列表时。您很可能需要排队。而是在Java中使用“阻塞队列”。 (3认同)

ass*_*ias 23

只要你不要求"删除"方法是原子的,这应该没问题.

换句话说,如果"执行某事"检查项目在列表中出现多次,则到达下一行时,该检查的结果可能会出错.

此外,请确保在迭代时在列表上进行同步:

synchronized(list) {
    for (Object o : list) {}
}
Run Code Online (Sandbox Code Playgroud)

正如Peter Lawrey所提到的,CopyOnWriteArrayList可以让您的生活更轻松,并且可以在高度并发的环境中提供更好的性能.


gku*_*min 12

来自Collections#synchronizedList(List)javadoc

返回由指定列表支持的同步(线程安全)列表.为了保证串行访问,关键是 所有对备份列表的访问都是通过返回的列表完成的......当迭代时,用户必须手动同步返回的列表.不遵循此建议可能会导致非确定性行为.