460 Stimmen

Wie kann man mit ExecutorService warten, bis alle Threads beendet sind?

Ich muss eine gewisse Anzahl von Aufgaben 4 auf einmal ausführen, etwa so:

ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
    taskExecutor.execute(new MyTask());
}
//...wait for completion somehow

Wie kann ich benachrichtigt werden, wenn sie alle abgeschlossen sind? Im Moment fällt mir nichts Besseres ein, als einen globalen Aufgabenzähler zu setzen und ihn am Ende jeder Aufgabe zu verringern und dann in einer Endlosschleife zu überwachen, dass dieser Zähler 0 wird; oder eine Liste von Futures zu erhalten und in einer Endlosschleife isDone für alle zu überwachen. Was sind bessere Lösungen, die keine Endlosschleifen beinhalten?

Danke.

1voto

Alex Martelli Punkte 805329

Sie könnten Ihre eigene Unterklasse von ExecutorCompletionService zum Einwickeln taskExecutor und Ihre eigene Implementierung von BlockingQueue um informiert zu werden, wenn eine Aufgabe abgeschlossen ist, und um einen Rückruf oder eine andere gewünschte Aktion durchzuführen, wenn die Anzahl der abgeschlossenen Aufgaben das gewünschte Ziel erreicht.

1voto

Dr. X Punkte 2729

Wenn Sie mehrere Thread-Ausführungsdienste nacheinander verwenden und warten wollen, bis JEDER AUSFÜHRUNGSDIENST beendet ist. Der beste Weg ist wie unten;

ExecutorService executer1 = Executors.newFixedThreadPool(THREAD_SIZE1);
for (<loop>) {
   executer1.execute(new Runnable() {
            @Override
            public void run() {
                ...
            }
        });
} 
executer1.shutdown();

try{
   executer1.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);

   ExecutorService executer2 = Executors.newFixedThreadPool(THREAD_SIZE2);
   for (true) {
      executer2.execute(new Runnable() {
            @Override
            public void run() {
                 ...
            }
        });
   } 
   executer2.shutdown();
} catch (Exception e){
 ...
}

0voto

Vlad Punkte 9

Java 8 - Wir können Stream-API verwenden, um Stream zu verarbeiten. Bitte sehen Sie das folgende Snippet

final List<Runnable> tasks = ...; //or any other functional interface
tasks.stream().parallel().forEach(Runnable::run) // Uses default pool

//alternatively to specify parallelism 
new ForkJoinPool(15).submit(
          () -> tasks.stream().parallel().forEach(Runnable::run) 
    ).get();

0voto

Pengfei Zhan Punkte 65
ExecutorService WORKER_THREAD_POOL 
  = Executors.newFixedThreadPool(10);
CountDownLatch latch = new CountDownLatch(2);
for (int i = 0; i < 2; i++) {
    WORKER_THREAD_POOL.submit(() -> {
        try {
            // doSomething();
            latch.countDown();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    });
}

// wait for the latch to be decremented by the two remaining threads
latch.await();

Wenn doSomething() einige andere Ausnahmen auslösen, wird die latch.countDown() scheint nicht ausgeführt zu werden, was soll ich also tun?

-1voto

Matej Tymes Punkte 1706

Sie könnten anrufen waitTillDone() hierauf Läufer Klasse:

Runner runner = Runner.runner(4); // create pool with 4 threads in thread pool

while(...) {
    runner.run(new MyTask()); // here you submit your task
}

runner.waitTillDone(); // and this blocks until all tasks are finished (or failed)

runner.shutdown(); // once you done you can shutdown the runner

Sie können Wiederverwendung diese Klasse und rufen Sie waitTillDone() beliebig oft auf, bevor Sie shutdown() aufrufen, und Ihr Code ist sehr einfach . Auch Sie müssen nicht wissen die Anzahl der Aufgaben im Voraus.

Um es zu verwenden, fügen Sie einfach dieses gradle/maven compile 'com.github.matejtymes:javafixes:1.3.1' Abhängigkeit zu Ihrem Projekt.

Weitere Einzelheiten finden Sie hier:

https://github.com/MatejTymes/JavaFixes

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X