我正在使用ArrayList尝试生产者和消费者问题(我知道Arraylist不是线程安全的),我确保我使用snapshots
关键字列出但仍然进入synchronized
。这是错误
启动制作人请提供作业详细信息:TestJob Job 已完成:线程“消费者”中的TestJob异常 java.util.ConcurrentModificationException at java.util.ArrayList $ Itr.checkForComodification(Unknown Source)at java.util.ArrayList $ Itr.next(未知来源)at test.thread.Consumer.run(Consumer.java:25)at java.lang.Thread.run(未知来源)
这是我的代码:
ConcurrentModificationException
答案 0 :(得分:3)
您无法从使用增强型for语句进行迭代的列表中删除项目。
如果要删除元素,则需要一个显式迭代器来调用remove:
Iterator<String> it = jobs.iterator();
while (it.hasNext()) {
String job = it.next();
System.out.println("Job completed: " + job);
it.remove();
Thread.sleep(2000);
}
当然,从像这样的ArrayList中删除项目是非常低效的(它是O(n^2)
),并且容易出错,因为你必须明确同步。您应该考虑使用某种BlockingQueue
代替。
答案 1 :(得分:3)
虽然你得到ConcurrentModificationException
,但问题不是由多线程引起的。
实际上这是有问题的代码:
for (String job : jobs) {
System.out.println("Job completed: " + job);
jobs.remove(job);
Thread.sleep(2000);
}
for
循环将在作业上使用Iterator
,同时您直接(在结构上)修改jobs
(即不通过Iterator
)。这意味着Iterator
不再是明确定义的,它会抛出此异常来告诉您。{/ p>
如果您需要在迭代时删除集合中的元素,则需要明确Iterator
:
Iterator<String> jobIterator = job.iterator();
while (jobIterator.hasNext()) {
String job = jobIterator.next();
// ... stuff ...
jobIterator.remove(); // remove the last object that was returned by next()
}
答案 2 :(得分:2)
您的并发修改不是由线程引起的。
for (String job : jobs) {
System.out.println("Job completed: " + job);
jobs.remove(job);
Thread.sleep(2000);
}
在您迭代时,行jobs.remove(job);
会修改ArrayList。迭代器只允许在使用Iterators remove方法完成后修改列表。
for( Iterator<String> iter = jobs.iterator(); iter.hasNext(); )
{
String job = iter.next();
iter.remove();
}
答案 3 :(得分:1)
你得到ConcurrentModificationException不是因为并发:你只需要在循环中删除项目:
for (String job : jobs) {
System.out.println("Job completed: " + job);
jobs.remove(job);
使用迭代器删除项目。
答案 4 :(得分:0)
在使用列表CopyOwWriteArrayList
时,您应该使用ConcurrentModificationException
来阻止Iterator
(代码中的每个循环都会在引擎盖下使用它)
答案 5 :(得分:0)
无法删除元素,请使用迭代器方法删除。
Iterator<String> it = jobs.iterator();
while(it.hasNext()) {
String job = it.next();
....
it.remove();
...
}
这将避免concurrentModificationException。