使用CompletableFuture直接将代码直接传递给线程有什么好处?
Thread thread = new Thread(() -> {do something});
thread.start();
VS
CompletableFuture<Void> cf1 =
CompletableFuture.runAsync(() -> {do something});
答案 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个或多个线程。