7

在下面的代码中,调用thenRunAsync有什么不同吗?我应该只调用thenRun吗?

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

针对评论进行详细说明:如果我要改用此代码,

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

它的行为会有什么不同吗?

在这两种情况下,行为都是非阻塞的,并且第二个任务在第一个任务完成之前不会运行,据我所知,无论如何。

4

1 回答 1

16

如果已经完成,该方法thenRun允许Runnable直接在调用者的线程中执行。CompletableFuture因为即使在像CompletableFuture.runAsync(…).thenRun(…);这样的直接调用链中,异步任务也有可能在被调用时已经完成thenRun,所以依赖动作有可能在调用者的线程中执行,thenRunAsync这与总是使用默认(或提供的)执行程序不同.

所以一句话,是的,它有所作为。


顺便说一句, using 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 池,并且只有两个参数thenRunAsync将始终使用提供的执行程序。

于 2016-04-07T10:17:52.857 回答