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代わりにを使用することを検討してみませんか? implementを作成WorkerCallableてから、サービスのinvokeAll()メソッドの 1 つを使用します。

CyclicBarrierまたはCountDownLatch、同様の機能を構築するために使用できる低レベルのツールです。

于 2011-06-06T21:45:36.110 に答える
2

Iterator が部分的に完了しているときにリストを変更しようとすると ConcurrentModificationException が発生しますが、コード サンプルにはリストに追加またはリストから削除するコードがないため、問題はコードの別の場所にあります。

基本的に、Interator を使用している間はリストから削除または追加しないでください。削除する必要がある場合は、List.remove() の代わりに Iterator.remove() を使用してアイテムを削除できます。

于 2011-06-06T21:44:31.840 に答える