线程与CompletableFuture

时间:2018-04-16 19:53:19

标签: java multithreading java-8 completable-future

使用CompletableFuture直接将代码直接传递给线程有什么好处?

Thread thread = new Thread(() -> {do something});
thread.start();

VS

CompletableFuture<Void> cf1 =  
     CompletableFuture.runAsync(() -> {do something}); 

3 个答案:

答案 0 :(得分:13)

CompletableFuture.runAsync(...)在forkJoin-Pool中运行Runnable,其中被管理,而new Thread()创建一个新的线程你必须管理

“被管理”是什么意思,它是预先分配的,并且线程在JVM中共享。当runnable完成后,该线程可以重用于其他runnables。这样可以更好地利用资源,特别是当线程实例化是一项昂贵的操作时 - 不仅要对象,而且还需要分配一些额外的非堆内存 - 线程堆栈。

答案 1 :(得分:3)

@GeraldMücke已经提到了重要的区别:

  

CompletableFuture.runAsync(...)在受管理的forkJoin-Pool中运行Runnable,而new Thread()创建一个必须管理的新线程。

CompletableFuture将使用由 ThreadPool (默认或自定义)管理的线程。

但是,我认为还应该考虑以下两点。

第一

CompletableFuture具有许多易于理解的方法,可以将不同的异步计算链接在一起,与直接使用 Thread 相比,引入异步要容易得多。

CompletableFuture[] futures = IntStream.rangeClosed(0, LEN).boxed()
            .map(i -> CompletableFuture.supplyAsync(() -> runStage1(i), EXECUTOR_SERVICE))
            .map(future -> future.thenCompose(i -> CompletableFuture.supplyAsync(() -> runStage2(i), EXECUTOR_SERVICE)))
            .toArray(size -> new CompletableFuture[size]);
CompletableFuture.allOf(futures).join();

第二

您永远不要忘记处理异常,使用CompletableFuture,您可以按以下方式直接处理它们:

completableFuture.handle((s, e) -> e.toString()).join()

或利用它们来中断计算:

completableFuture.completeExceptionally(new RuntimeException("Calculation failed!"));

使用 Thread 可以轻松遇到一些严重的问题。

答案 2 :(得分:0)

CompletableFuture是一个使用默认ForkJoinPool(大小等于CPU数量的线程池)的承诺,除非提供了另一个ThreadPool。一个线程池将包含n个或多个线程。