我正在使用SynchronizedCollection.containsAll
面临的问题是当我运行以下代码时,我得到ConcurrentModification Exception
。
从我的理解代码应该终止,没有任何例外。
public class Main {
public static void main(String[] args) {
List l1 = new LinkedList(), l2 = new LinkedList();
for (int i = 0; i < 100000; i++) {
l1.add("" + i);
}
for (int i = 0; i < 100000; i++) {
l2.add("" + i);
}
// reverse to make the search take a little longer
Collections.reverse(l2);
final List sl1 = Collections.synchronizedList(l1);
final List sl2 = Collections.synchronizedList(l2);
new Thread() {
public void run() {
// synchronized (sl2) {
sl1.containsAll(sl2);
// }
}
}.start();
new Thread() {
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
sl2.add("3");
}
}.start();
}
}
有人可以帮助我理解为什么我会得到这个例外。
答案 0 :(得分:2)
根据the documentation of Collections::synchronizedList
当迭代它时,用户必须手动同步返回的列表。
在您的示例中,当您运行sl.containsAll(sl2)
时,您将在sl2
上进行迭代,而无需在sl2
上进行同步。这无疑是containsAll
方法的实现细节,但it is clearly indicated in the javadoc:
此实现迭代指定的集合,依次检查迭代器返回的每个元素,看它是否包含在此集合中。
您可以通过sl2
上的同步来解决问题(即取消注释掉已注释掉的代码)。
答案 1 :(得分:0)
我检查了代码,我认为异常是有意的,但如果是当前代码
public boolean containsAll(Collection<?> coll) {
synchronized(mutex) {return c.containsAll(coll);}
}
更改为....
public boolean containsAll(Collection<?> coll) {
synchronized(mutex) {
synchronized(coll) {
return c.containsAll(coll);}}
}
然后问题就解决了。