Как можно просто дождаться завершения всех потоковых процессов? Например, допустим, у меня есть:
public class DoSomethingInAThread implements Runnable{
public static void main(String[] args) {
for (int n=0; n<1000; n++) {
Thread t = new Thread(new DoSomethingInAThread());
t.start();
}
// wait for all threads' run() methods to complete before continuing
}
public void run() {
// do something here
}
}
Как мне изменить это так, чтобы main()
метод останавливался на комментарии, пока все run()
методы потоков не завершились? Спасибо!
java
multithreading
parallel-processing
wait
DivideByHero
источник
источник
Один из способов - создать a
List
изThread
s, создать и запустить каждый поток, добавляя его в список. Как только все будет запущено, вернитесь к списку и вызовитеjoin()
каждый из них. Не имеет значения, в каком порядке завершаются выполнение потоков, все, что вам нужно знать, это то, что к тому времени, когда завершится выполнение второго цикла, все потоки будут завершены.Лучшим подходом является использование ExecutorService и связанных с ним методов:
Использование ExecutorService (и всех новых вещей из утилит параллелизма Java 5 ) невероятно гибко, и приведенный выше пример едва ли затрагивает поверхность.
источник
источник
вместо
join()
старого API можно использовать CountDownLatch . Я изменил ваш код, как показано ниже, чтобы выполнить ваше требование.Пояснение :
CountDownLatch
был инициализирован с заданным счетчиком 1000 согласно вашему требованию.Каждый рабочий поток
DoSomethingInAThread
будет уменьшать значениеCountDownLatch
, переданное в конструктор.Основной поток,
CountDownLatchDemo
await()
пока счетчик не станет равным нулю. Как только счетчик станет нулевым, вы увидите строку ниже на выходе.Дополнительная информация на странице документации Oracle
Обратитесь к соответствующему вопросу SE для других вариантов:
подождите, пока все потоки закончат свою работу в java
источник
Полностью избегайте класса Thread и вместо этого используйте более высокие абстракции, представленные в java.util.concurrent
Класс ExecutorService предоставляет метод invokeAll, который, кажется, делает именно то, что вы хотите.
источник
Рассмотрите возможность использования
java.util.concurrent.CountDownLatch
. Примеры в javadocsисточник
Как предложил Мартин К., это
java.util.concurrent.CountDownLatch
кажется лучшим решением для этого. Просто добавляю пример того жеисточник
В зависимости от ваших потребностей, вы также можете проверить классы CountDownLatch и CyclicBarrier в пакете java.util.concurrent. Они могут быть полезны, если вы хотите, чтобы ваши потоки ожидали друг друга, или если вы хотите более детальный контроль над тем, как ваши потоки выполняются (например, ожидая в своем внутреннем исполнении, чтобы другой поток установил какое-то состояние). Вы также можете использовать CountDownLatch, чтобы сигнализировать всем вашим потокам о запуске одновременно, вместо того, чтобы запускать их один за другим, когда вы повторяете свой цикл. В стандартных документах API есть пример этого, а также использование другого CountDownLatch для ожидания завершения выполнения всеми потоками.
источник
Если вы составите список потоков, вы можете перебрать их и выполнить .join () для каждого, и ваш цикл завершится, когда все потоки будут. Но я не пробовал.
http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join ()
источник
Создайте объект потока внутри первого цикла for.
Итак, что все здесь говорят.
источник
Вы можете сделать это с помощью объекта ThreadGroup и его параметра activeCount :
источник
В качестве альтернативы CountDownLatch вы также можете использовать CyclicBarrier, например
Чтобы использовать CyclicBarrier в этом случае, в последнем операторе должен быть барьер .await (), т.е. когда ваш поток завершил свою работу. CyclicBarrier можно снова использовать с его методом reset (). Чтобы процитировать javadocs:
CyclicBarrier поддерживает необязательную команду Runnable, которая запускается один раз для каждой точки барьера после прибытия последнего потока в группе, но до того, как какие-либо потоки будут освобождены. Это действие барьера полезно для обновления общего состояния до продолжения какой-либо из сторон.
источник
join()
Не было полезно для меня. см. этот образец в Котлине:Результат:
Теперь позвольте мне использовать
join()
для потоков:И результат:
Это ясно, когда мы используем
join
:Нашим решением для предотвращения блокировки других потоков было создание ArrayList:
Теперь, когда мы хотим запустить новый поток, мы чаще всего добавляем его в ArrayList:
addThreadToArray
Функция:startNewThread
Funstion:Проверяйте завершение потоков, как показано ниже, везде, где это необходимо:
источник