在多线程模块中,我不关心它是否通过线程安全地写入java.util.Collection
(例如java.util.Set
)对象。它的作用是通过多个线程删除一些独立元素,这可能同时对同一元素执行删除。那么,会发生什么?该元素被删除,或者抛出任何异常?
克加
答案 0 :(得分:5)
当您删除不同的对象时,甚至可能抛出ConcurrentModificationException。这取决于您正在使用的Set的实现:remove()方法可以迭代该集合。或者更糟糕的是:它可能会修改其他一些内部变量,并使该集合处于不一致状态而不会抛出任何异常。
有一个非常简单的解决方案:
Set safeSet = Collections.synchronizedSet(set);
如果你想迭代它,你仍然需要注意,如apidoc:http://download.oracle.com/javase/6/docs/api/java/util/Collections.html#synchronizedSet%28java.util.Set%29所述,但所有其他方法(包括删除)都没问题。
答案 1 :(得分:2)
结果无法预测。 Set
的内部结构可能处于不一致且不可用的状态。
答案 2 :(得分:2)
'ConcurrentModificationException'如果你幸运的话。如果没有混乱。无论是使用Collections.synchronized *还是在其他对象上进行同步,都不要这样做。
答案 3 :(得分:2)
java.util.Set只是一个接口。行为取决于Set接口的实现。您不能使用多个线程访问HashSet,因为行为无法保证,但如果您这样做,可能会抛出ConcurrentModificationException。
答案 4 :(得分:1)
你可能不在乎,因为如果你这样做,你会认为Set会保持其完整性。但它不会。
您需要Collections.newSetFromMap(new ConcurrentHashMap<E, Boolean>());
或使用某些同步。去除不是这里唯一的问题。如果您只使用HashSet,您也可以在Set中找到重复项,或者知道还有什么。
给定一个适当的Set实现来处理线程问题,然后一个线程将删除该项,另一个将找到不存在的项,这可以通过Set上的remove方法的返回值来确定。
请注意,如果要迭代集合,则在迭代期间删除元素时必须使用一些外部同步。