Java 线程与可完成的未来
与使用CompletableFuture相比,直接将代码传递给线程有什么好处Java 线程与可完成的未来,java,multithreading,java-8,completable-future,Java,Multithreading,Java 8,Completable Future,与使用CompletableFuture相比,直接将代码传递给线程有什么好处 Thread thread = new Thread(() -> {do something}); thread.start(); VS CompletableFuture cf1= runAsync(()->{do something}); CompletableFuture.runAsync(…)在被管理的forkJoin池中运行Runnable,而new Thread()创建您必须管理的新线程 “被管理”
Thread thread = new Thread(() -> {do something});
thread.start();
VS
CompletableFuture cf1=
runAsync(()->{do something});
CompletableFuture.runAsync(…)
在被管理的forkJoin池中运行Runnable,而new Thread()
创建您必须管理的新线程
“被管理”意味着什么,它是预先分配的,线程在JVM中共享。当runnable完成时,该线程可以重新用于其他runnable。这可以更好地利用资源,特别是因为线程实例化是一项昂贵的操作——不仅是对象,还必须分配一些额外的非堆内存——线程堆栈。@Gerald Mücke已经提到了重要的区别: runAsync(…)在被管理的forkJoin池中运行Runnable,而new Thread()创建一个必须管理的新线程 CompletableFuture将使用由线程池(默认或自定义)管理的线程 不过,我认为以下两点也是应该考虑的 弗斯特 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!"));
虽然使用线程很容易遇到一些严重问题,但CompletableFuture承诺使用默认的ForkJoinPool(大小等于CPU数量的线程池),除非提供另一个线程池。一个线程池将包含n个或更多的线程。如果我使用
线程,我还必须做些什么。从管理角度来说,开始使用方法?Re“…你必须管理它。”不,你不必管理它。您可以创建一个新线程,启动它,然后忘记它。除了创建和销毁新线程的费用外,没有其他惩罚。@jameslarg谢谢!从来没有直接使用过线程,总是使用执行器,所以我没有意识到这一点。@jameslarge“除了创建和销毁线程的成本外,没有其他惩罚”,你让人觉得每个人都有无限的内核,而运行线程的成本是零。嗯,这需要CPU时间,这也是使用poolsSome语句的原因之一。这里的语句似乎有点过于泛化了(@Cargeh和james large)。线程不仅用于利用可用的处理资源(核心),还用于隐藏延迟或执行非阻塞操作——即使(新)线程主要在等待(例如IO)。拥有一个包含n
线程的池是没有意义的,这些线程都在等待(不存在的)n+1
第个线程应该做的事情。当然,这些东西通常被抽象层和库隐藏起来。但是手动创建一个新线程是非常好的——即使你“有经验”。
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();