Как использовать Thread.join () для всех элементов списка с изменяющимся размером? - PullRequest
2 голосов
/ 07 июня 2011

Допустим, у меня активно обрабатывается большое количество рабочих потоков, а также поток супервизора, который ожидает их завершения. Традиционно я мог сделать что-то вроде:

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

... что мне кажется странным, потому что я думал, что как только вы получите итератор, он будет отделен от самого списка. Моя следующая идея - клонировать список итераторов или сотрудников таким образом, чтобы он отделился от первоначального списка изменений, но я подумал, что сначала я дам вам экспертные рекомендации.

Ответы [ 2 ]

4 голосов
/ 07 июня 2011

Экземпляр Iterator становится недействительным, если в базовую коллекцию внесены какие-либо изменения вне экземпляра Iterator.

Почему бы вам не рассмотреть возможность использования ExecutorService вместо этого?Сделайте Worker внедрите Callable, затем используйте один из методов invokeAll() службы.

CyclicBarrier или CountDownLatch являются инструментами более низкого уровня, которые можно использовать для создания аналогичной функции.

2 голосов
/ 07 июня 2011

Вы получаете исключение ConcurrentModificationException при попытке изменить список, когда итератор частично завершен, однако в ваших примерах кода нет кода, который добавляет или удаляет из списка, поэтому проблема в другом месте вашего кода.

По сути, не удаляйте и не добавляйте из списка, когда вы используете Interator, вы можете удалить элементы, используя Iterator.remove () вместо List.remove (), если вам нужно удалить.

...