如何对大小不断变化的列表的所有元素进行 Thread.join() ?

发布于 2024-11-14 13:27:26 字数 1007 浏览 5 评论 0原文

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

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();

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

Lets say I have a large number of worker threads all actively processing, and a supervisor thread that waits for them all to complete. Traditionally I could do something like:

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

..and all would be well. However in this case the size of my worker list (ArrayList staff) is variable and may change at arbitrary times. My best knowledge tells me something like this should work:

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;}
}

This however, still results in a conncurrentModificationException on the line

Worker w = it.next();

...which to me seems strange, because I thought that once you retrieved the iterator it was separate from the list itself. My next idea is to clone the iterator or staff list so that it IS separate from the original changing list, but I thought I would give you experts a shot at it first.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

转身以后 2024-11-21 13:27:26

如果对 Iterator 实例外部的底层集合进行任何更改,则 Iterator 实例将失效。

您为什么不考虑使用 ExecutorService 来代替?让 Worker 实现 Callable,然后使用该服务的其中一个 invokeAll() 方法。

CyclicBarrierCountDownLatch 是较低级别的工具,可用于构建类似的功能。

An Iterator instance is invalidated if any changes are made to the underlying collection outside of the Iterator instance.

Why don't you consider using an ExecutorService instead? Make Worker implement Callable, then use one of the service's invokeAll() methods.

CyclicBarrier or CountDownLatch are lower-level tools that can be used to build similar function.

一场信仰旅途 2024-11-21 13:27:26

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

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

You get a ConcurrentModificationException when you try to modify a list while an Iterator is partially complete however in your code samples there is no code which adds or removes from the list therefore the problem is elsewhere in your code.

Basically don't remove or add from the list while you are using an Interator, you can remove items using Iterator.remove() instead of List.remove() if you have to remove.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文