线程与 CompletableFuture
Thread vs CompletableFuture
将代码直接传递给线程与使用 CompletableFuture 相比有什么优势?
Thread thread = new Thread(() -> {do something});
thread.start();
VS
CompletableFuture<Void> cf1 =
CompletableFuture.runAsync(() -> {do something});
CompletableFuture.runAsync(...)
在 管理的 forkJoin-Pool 中运行 Runnable,而 new Thread()
创建一个新线程, 你有管理.
"is managed"是什么意思,它是预分配的,线程是在JVM中共享的。当 runnable 完成时,线程可以被其他 runnable 重用。这可以更好地利用资源,特别是因为线程实例化是一项昂贵的操作 - 不仅是对象,还有一些额外的非堆内存 - 线程堆栈 - 必须分配。
@Gerald Mücke 已经提到了重要的区别:
CompletableFuture.runAsync(...) runs the Runnable in the forkJoin-Pool which is managed, while new Thread() creates a new thread which you have to manage.
CompletableFuture 将使用由 ThreadPool(默认或自定义)管理的线程。
不过,我觉得下面两点也是应该考虑的。
第一个
CompletableFuture 有很多简单易懂的方法将不同的异步计算链接在一起,引入异步比直接使用线程.
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.
很容易遇到一些严重的问题
CompletableFuture 是一个使用默认 ForkJoinPool(大小等于 CPU 的线程池)的承诺,除非提供另一个线程池。一个线程池将包含 n 个或更多数量的线程。
将代码直接传递给线程与使用 CompletableFuture 相比有什么优势?
Thread thread = new Thread(() -> {do something});
thread.start();
VS
CompletableFuture<Void> cf1 =
CompletableFuture.runAsync(() -> {do something});
CompletableFuture.runAsync(...)
在 管理的 forkJoin-Pool 中运行 Runnable,而 new Thread()
创建一个新线程, 你有管理.
"is managed"是什么意思,它是预分配的,线程是在JVM中共享的。当 runnable 完成时,线程可以被其他 runnable 重用。这可以更好地利用资源,特别是因为线程实例化是一项昂贵的操作 - 不仅是对象,还有一些额外的非堆内存 - 线程堆栈 - 必须分配。
@Gerald Mücke 已经提到了重要的区别:
CompletableFuture.runAsync(...) runs the Runnable in the forkJoin-Pool which is managed, while new Thread() creates a new thread which you have to manage.
CompletableFuture 将使用由 ThreadPool(默认或自定义)管理的线程。
不过,我觉得下面两点也是应该考虑的。
第一个
CompletableFuture 有很多简单易懂的方法将不同的异步计算链接在一起,引入异步比直接使用线程.
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.
很容易遇到一些严重的问题CompletableFuture 是一个使用默认 ForkJoinPool(大小等于 CPU 的线程池)的承诺,除非提供另一个线程池。一个线程池将包含 n 个或更多数量的线程。