CompletableFuture runAsync与新线程

时间:2018-07-03 12:52:04

标签: java multithreading asynchronous concurrency java-8

上下文:我已阅读this SO线程,讨论CompletableFuture和Thread之间的区别。

但是我试图理解何时我应该使用新的Thread()而不是runAsync()。

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

在考虑使用一种方法之前,我应该了解哪些因素?

谢谢大家。

2 个答案:

答案 0 :(得分:4)

使用低级并发API(例如Thread)与其他API的区别不仅在于您要完成的工作类型,还在于编程模型以及它们使它易于配置的能力任务运行的环境。

通常,建议使用更高级别的API,例如CompletableFuture,而不是直接使用Thread

  

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

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

使用ExecutorService来更好地控制线程池,并且通常将CompletableFuture.runAsyncCompletableFuture.supplyAsync与指定的执行器服务一起使用(或不使用)来创建和运行{{ 1}}对象。

对于长时间运行的任务,没有特别支持或反对使用CompletableFuture API。但是,选择使用Thread的选择还具有其他含义,其中包括:

  • Thread为响应式编程提供了更好的API,而无需强迫我们编写显式的同步代码。 (当直接使用线程时我们不会得到这个)
  • CompletableFuture接口(由Future实现)还具有其他明显的优点。

因此,简而言之:您可以(如果应该考虑使用的替代方法是CompletableFuture API,则可以使用Thread API来执行长时间运行的任务。为了更好地控制线程池,可以将其与执行程序服务结合使用。

答案 1 :(得分:2)

主要区别是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");
    });

输出:

On first task
Thread : Thread[ForkJoinPool.commonPool-worker-1,5,main]
On second task

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

  

注意:线程是ForkJoinPool.commonPool中的守护程序。