How to Thread.join() on all elements of a list of changing size?
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 separ开发者_Python百科ate 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.
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.
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.
精彩评论