Java同步列表
我有一个预先填充的数组列表。 我有多个线程将从数组列表中删除元素。 每个线程调用下面的remove方法,并从列表中删除一个项目。 下面的代码是否给我一致的行为?
ArrayList<String> list = Collections.synchronizedList(new ArrayList<String>()); void remove(String item) { do something; (doesn't work on the list) list.remove(item); }
谢谢!
是的,如果您也在迭代列表,请小心,因为在这种情况下,您需要同步它。 从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
写入速度较慢但不存在此问题。
这应该没问题,只要你不需要“删除”的方法是primefaces的。
换句话说,如果“执行某些事情”检查该项目在列表中多次出现,例如,在到达下一行时,检查结果可能是错误的。
另外,确保在迭代时同步列表中的内容:
synchronized(list) { for (Object o : list) {} }
正如Peter Lawrey所提到的, CopyOnWriteArrayList可以让您的生活更轻松,并且可以在高度并发的环境中提供更好的性能。
来自Collections#synchronizedList(List)
javadoc
返回由指定列表支持的同步(线程安全)列表。 为了保证串行访问,通过返回的列表来完成对后备列表的所有访问是至关重要的…用户必须在迭代时手动同步返回的列表。 不遵循这个build议可能会导致非确定性的行为。
列表中可能有两个不同的问题:
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)第二个问题可能是multithreading环境。 如上所述,您可以使用synchronized(list)来避免exception。
它会为添加/删除操作提供一致的行为。 但是在迭代的时候,你必须明确同步。 参考这个链接
是的,它会正常工作,因为你已经synchronized
列表。 我build议你使用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); }
synchronized(list) { for (Object o : list) {} }