CompletableFuture runAsync 与新线程

The*_*ice 7 java concurrency multithreading asynchronous java-8

语境:我读过这个SO线程讨论CompletableFuture和线程之间的差异。

但我试图了解何时应该使用 new Thread() 而不是 runAsync()。

我知道 runAsyn() 对于短/一次性并行任务更有效,因为我的程序可能会避免创建全新线程的开销,但我是否也应该考虑它用于长时间运行的操作?

在考虑使用一个而不是另一个之前,我应该了解哪些因素?

谢谢大家。

ern*_*t_k 8

使用低级并发 API(例如 Thread)和其他 API 之间的区别不仅在于您想要完成的工作类型,还在于编程模型以及它们如何轻松地配置环境任务运行。

一般情况下,建议使用更高级别的 API,例如CompletableFuture不要直接使用Threads。

我知道 runAsyn() 对于短/一次性并行任务更有效

好吧,也许,假设您调用runAsync,指望它使用 fork-join 池。该runAsync方法重载了一种方法,该方法允许指定java.util.concurrent.Executor执行异步任务的方法。

使用ExecutorService对线程池的更多控制和使用CompletableFuture.runAsyncCompletableFuture.supplyAsync使用指定的执行程序服务(或不使用)通常比Thread直接创建和运行对象更受欢迎。

没有什么特别赞成或反对将 CompletableFuture API 用于长时间运行的任务。但是选择使用Threads 也有其他含义,其中包括:

  • CompletableFuture为响应式编程提供了更好的 API,而无需强制我们编写显式的同步代码。(直接使用线程时我们没有得到这个)
  • Future接口(由实施CompletableFuture)给出的其它附加,优势明显。

因此,简而言之:您可以(并且可能应该,如果正在考虑的替代方案是ThreadAPI)将CompletableFutureAPI 用于您的长时间运行的任务。为了更好地控制线程池,您可以将其与执行程序服务结合使用。


Ami*_*era 6

主要区别在于CompletableFuture默认情况下在ForkJoinPool.commonPool. 但是,如果您创建自己的线程并启动它,它将作为单个线程执行,而不是在线程池上执行。此外,如果您想按顺序执行某些任务,但是asynchronously. 然后你可以像下面这样做。

    CompletableFuture.runAsync(() -> {
        System.out.println("On first task");
        System.out.println("Thread : " + Thread.currentThread());
    }).thenRun(() -> {
        System.out.println("On second task");
    });
Run Code Online (Sandbox Code Playgroud)

输出:

On first task
Thread : Thread[ForkJoinPool.commonPool-worker-1,5,main]
On second task
Run Code Online (Sandbox Code Playgroud)

如果您运行上面的代码,您可以看到CompletableFuture正在使用哪个池。

注意:Threads 是ForkJoinPool.commonPool.