Die Methode thenRun
ermöglicht die Ausführung der Runnable
direkt im Thread des Aufrufers, wenn die CompletableFuture
bereits abgeschlossen ist. Da selbst in einer direkten Aufrufkette wie CompletableFuture.runAsync(…).thenRun(…);
die Möglichkeit besteht, dass die asynchrone Task bereits zum Zeitpunkt thenRun
aufgerufen wurde, besteht die Möglichkeit, dass die abhängige Aktion im Thread des Aufrufers ausgeführt wird, im Gegensatz zu thenRunAsync
, die immer den Standard (oder zur Verfügung gestellt) Executor.
Also in einem Satz, ja, es macht einen Unterschied.
By the way, mit thenRunAsync
(der einzigen Argumente Version) wird die Aktion mit den Executor
wieder auf den Werks- Anruf, aber der Executor
Standard geliefert nicht ausgeführt werden.
Sie können ganz einfach die verschiedenen Verhaltensweisen vergleichen:
public static void main(String[] args) {
ExecutorService e=Executors.newSingleThreadExecutor(r -> new Thread(r, "sole thread"));
CompletableFuture<?> f=CompletableFuture.runAsync(()->{}, e);
f.join();
f.thenRun(()->System.out.println("thenRun:\t"+Thread.currentThread()));
f.thenRunAsync(()->System.out.println("thenRunAsync:\t"+Thread.currentThread()));
f.thenRunAsync(()->System.out.println("thenRunAsync+e:\t"+Thread.currentThread()), e);
e.shutdown();
}
druckt
thenRun: Thread[main,5,main]
thenRunAsync: Thread[ForkJoinPool.commonPool-worker-1,5,main]
thenRunAsync+e: Thread[sole thread,5,main]
während
public static void main(String[] args) {
ExecutorService e=Executors.newSingleThreadExecutor(r -> new Thread(r, "sole thread"));
CompletableFuture<?>f=CompletableFuture.runAsync(()->LockSupport.parkNanos((int)1e9),e);
f.thenRun(()->System.out.println("thenRun:\t"+Thread.currentThread()));
f.thenRunAsync(()->System.out.println("thenRunAsync:\t"+Thread.currentThread()));
f.thenRunAsync(()->System.out.println("thenRunAsync+e:\t"+Thread.currentThread()), e);
LockSupport.parkNanos((int)2e9);
e.shutdown();
}
thenRun: Thread[sole thread,5,main]
thenRunAsync: Thread[ForkJoinPool.commonPool-worker-1,5,main]
thenRunAsync+e: Thread[sole thread,5,main]
gedruckt werden
thenRun
So kann thenRun
die Aktion in entweder dem Thread des Aufrufers oder dem Executor
Thread ausführen, während das Einzelargument thenRunAsync
immer den Fork/Join-Pool verwendet und nur die beiden Argumente thenRunAsync
immer den bereitgestellten Executor verwenden.
Nun ist der Unterschied, dass "handleSuccess" asynchron aufgerufen wird, wenn "doWork" normal beendet wurde. Ich bin mir nicht sicher, welche Art von Antwort du suchst. – Tunaki
@Tunaki: Ich nehme an, die Frage zielt darauf ab, dass die an 'thenRun' übergebene Aktion auch asynchron ausgeführt wird (in Bezug auf den Thread, der' thenRun' aufruft), wenn die vorherige Stufe nicht bis zum Ende abgeschlossen ist der 'thenRun'-Aufruf. Aber anscheinend gibt es noch mehr Unterschiede, als die Frage anstrebt ... – Holger