2

假设我有大量工作线程都在积极处理,还有一个主管线程等待它们全部完成。传统上我可以做类似的事情:

for(Worker w:staff){
    w.start();
}
for(Worker w:staff){
    w.join();
}

..一切都会好起来的。但是在这种情况下,我的工作人员列表(ArrayList 员工)的大小是可变的,并且可能会在任意时间发生变化。我最好的知识告诉我这样的事情应该有效:

synchronized(this){
    for(Worker w:staff){
        w.start();
    }
}
while(true){ //this loop will keep the supervisor running until all workers have stopped
                  //interrupts will occur when changes to the size of staff list occur
    try{
        Iterator<Worker> it;
        synchronized(this){
            it = staff.iterator();
        }
        while(it.hasNext()){
            Worker w = it.next();
            w.join();
        }
        return;
    }catch(InterruptedException ie){continue;}
}

然而,这仍然会导致在线上的 conncurrentModificationException

Worker w = it.next();

...这对我来说似乎很奇怪,因为我认为一旦您检索到迭代器,它就会与列表本身分开。我的下一个想法是克隆迭代器或人员列表,使其与原始更改列表分开,但我想我会先让专家们了解一下。

4

2 回答 2

4

如果对实例Iterator之外的基础集合进行任何更改,则实例将失效Iterator

你为什么不考虑用一个ExecutorService代替?制作Workerimplement Callable,然后使用服务的invokeAll()方法之一。

CyclicBarrier或者CountDownLatch是可用于构建类似功能的较低级别的工具。

于 2011-06-06T21:45:36.110 回答
2

当您尝试在迭代器部分完成的情况下修改列表时,您会收到 ConcurrentModificationException,但是在您的代码示例中,没有从列表中添加或删除的代码,因此问题出在代码的其他地方。

基本上不要在使用 Interator 时从列表中删除或添加,如果必须删除,可以使用 Iterator.remove() 而不是 List.remove() 删除项目。

于 2011-06-06T21:44:31.840 回答