7

次のコードでは、thenRunAsyncを呼び出しても違いはありますか? 代わりにthenRunを呼び出す必要がありますか?

CompletableFuture.runAsync(this::doWork , executorService)
     .thenRunAsync(this::handleSuccess);

コメントに応じて詳しく説明します。代わりにこのコードを使用すると、

CompletableFuture.runAsync(this::doWork , executorService)
     .thenRun(this::handleSuccess);

それは何か違う振る舞いをしますか?

どちらの場合も、動作は非ブロックであり、2 番目のタスクは最初のタスクが完了するまで実行されません。

4

1 に答える 1

16

がすでに完了している場合、このメソッドを使用すると、呼び出し元のスレッドで直接thenRun実行できます。非同期タスクが呼び出されるまでに既に完了している可能性があるような直接呼び出しチェーンであっても、依存アクションが呼び出し元のスレッドで実行される可能性があります。 .RunnableCompletableFutureCompletableFuture.runAsync(…).thenRun(…);thenRunthenRunAsync

ですから、一言で言えば、そうです、それは違いを生みます。


ちなみに、thenRunAsync(単一引数バージョン)を使用するExecutorと、最初のファクトリ呼び出しに提供された を使用してアクションが実行されませんが、デフォルトのExecutor.

さまざまな動作を簡単に比較できます。

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

印刷します

thenRun:        Thread[main,5,main]
thenRunAsync:   Thread[ForkJoinPool.commonPool-worker-1,5,main]
thenRunAsync+e: Thread[sole thread,5,main]

一方

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]

そのthenRunため、呼び出し元のスレッドまたは のスレッドのいずれかでアクションを実行できExecutorますが、単一の引数thenRunAsyncは常に Fork/Join プールを使用し、2 つの引数のみthenRunAsyncが提供されたエグゼキューターを常に使用します。

于 2016-04-07T10:17:52.857 に答える