Jak można po prostu zaczekać na zakończenie całego procesu gwintowanego? Na przykład, powiedzmy, że mam:
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
}
}
Jak to zmienić, aby main()
metoda zatrzymywała się w komentarzu do momentu zakończenia wszystkich run()
metod wątków ? Dzięki!
java
multithreading
parallel-processing
wait
DivideByHero
źródło
źródło
Jednym ze sposobów byłoby zrobienie
List
zThread
s, utworzenie i uruchomienie każdego wątku podczas dodawania go do listy. Gdy wszystko zostanie uruchomione, wróć do listy i wywołajjoin()
każdą z nich. Nie ma znaczenia, w jakiej kolejności wątki kończą wykonywanie, wszystko, co musisz wiedzieć, to to, że do czasu zakończenia wykonywania drugiej pętli każdy wątek zostanie ukończony.Lepszym podejściem jest użycie ExecutorService i powiązanych z nim metod:
Korzystanie z usługi ExecutorService (i wszystkich nowych rzeczy z narzędzi współbieżności Java 5 ) jest niezwykle elastyczne, a powyższy przykład ledwo zarysowuje powierzchnię.
źródło
źródło
zamiast tego
join()
, który jest starym interfejsem API, możesz użyć CountDownLatch . Zmodyfikowałem Twój kod, jak poniżej, aby spełnić Twoje wymagania.Wyjaśnienie :
CountDownLatch
został zainicjowany z podaną liczbą 1000 zgodnie z wymaganiami.Każdy wątek roboczy
DoSomethingInAThread
zmniejszy wartośćCountDownLatch
, która została przekazana w konstruktorze.Główny wątek,
CountDownLatchDemo
await()
aż liczba osiągnie zero. Gdy liczba osiągnie zero, otrzymasz wynik poniżej linii.Więcej informacji na stronie dokumentacji oracle
Zobacz powiązane pytanie SE, aby uzyskać inne opcje:
poczekaj, aż wszystkie wątki zakończą swoją pracę w java
źródło
Całkowicie unikaj klasy Thread i zamiast tego używaj wyższych abstrakcji dostarczonych w java.util.concurrent
Klasa ExecutorService udostępnia metodę invokeAll, która wydaje się robić dokładnie to, co chcesz.
źródło
Rozważ użycie
java.util.concurrent.CountDownLatch
. Przykłady w javadocsźródło
Jak zasugerował Martin K.,
java.util.concurrent.CountDownLatch
wydaje się być lepszym rozwiązaniem. Dodam tylko przykład tego samegoźródło
W zależności od potrzeb możesz również chcieć sprawdzić klasy CountDownLatch i CyclicBarrier w pakiecie java.util.concurrent. Mogą być przydatne, jeśli chcesz, aby Twoje wątki czekały na siebie nawzajem lub jeśli chcesz mieć bardziej szczegółową kontrolę nad sposobem wykonywania wątków (np. Czekając w ich wewnętrznym wykonaniu, aż inny wątek ustawi jakiś stan). Możesz również użyć CountDownLatch, aby zasygnalizować wszystkie swoje wątki, aby rozpoczęły się w tym samym czasie, zamiast uruchamiać je jeden po drugim podczas iteracji w pętli. Standardowa dokumentacja API ma tego przykład, plus użycie innego CountDownLatch, aby poczekać, aż wszystkie wątki zakończą swoje wykonanie.
źródło
Jeśli utworzysz listę wątków, możesz je zapętlić i .join () względem każdego z nich, a pętla zakończy się, gdy wszystkie wątki będą miały. Jednak nie próbowałem tego.
http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join ()
źródło
Utwórz obiekt wątku wewnątrz pierwszej pętli for.
A potem to, co wszyscy tutaj mówią.
źródło
Możesz to zrobić za pomocą obiektu „ThreadGroup” i jego parametru activeCount :
źródło
Jako alternatywę dla CountDownLatch możesz również użyć CyclicBarrier np
Aby użyć CyclicBarrier w tym przypadku, barrier.await () powinno być ostatnią instrukcją, tj. Kiedy twój wątek kończy swoją pracę. CyclicBarrier może być ponownie użyty z jego metodą reset (). Cytując javadocs:
CyclicBarrier obsługuje opcjonalne polecenie Runnable, które jest uruchamiane raz na punkt bariery, po nadejściu ostatniego wątku w grupie, ale przed zwolnieniem jakichkolwiek wątków. Ta akcja bariery jest przydatna do aktualizowania stanu współużytkowanego, zanim którakolwiek ze stron będzie kontynuować.
źródło
To
join()
nie było dla mnie pomocne. zobacz tę próbkę w Kotlin:Wynik:
Teraz pozwól mi użyć
join()
dla wątków:A wynik:
Jak widać, gdy używamy
join
:Naszym rozwiązaniem zapobiegającym blokowaniu innych wątków było utworzenie ArrayList:
Teraz, gdy chcemy rozpocząć nowy wątek, najczęściej dodajemy go do ArrayList:
addThreadToArray
Funkcja:Funkcja
startNewThread
:Sprawdź wypełnienie wątków, jak poniżej, wszędzie tam, gdzie jest to potrzebne:
źródło