上下文:我已阅读this SO线程,讨论CompletableFuture和Thread之间的区别。
但是我试图理解何时我应该使用新的Thread()而不是runAsync()。
我了解runAsyn()对于短时间/一次性并行任务更有效,因为我的程序可能会避免创建全新线程的开销,但对于长时间运行的操作,我也应该考虑使用它吗?
在考虑使用一种方法之前,我应该了解哪些因素?
谢谢大家。
答案 0 :(得分:4)
使用低级并发API(例如Thread)与其他API的区别不仅在于您要完成的工作类型,还在于编程模型以及它们使它易于配置的能力任务运行的环境。
通常,建议使用更高级别的API,例如CompletableFuture
,而不是直接使用Thread
。
我知道runAsyn()对于短期/一次性并行任务更有效
好吧,也许,假设您调用runAsync
,请指望它使用fork-join池。 runAsync
方法重载了一种方法,该方法允许指定执行异步任务的java.util.concurrent.Executor
。
使用ExecutorService
来更好地控制线程池,并且通常将CompletableFuture.runAsync
或CompletableFuture.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
中的守护程序。