【问题标题】:Java 8 Completable FutureJava 8 可完成的未来
【发布时间】:2015-05-10 16:04:51
【问题描述】:

我的问题是如何使用 Completable Future。

我有一个实现 Callable 的类。

public class Executor implements Callable<Collection>

以前是用来做的-

service.submit(collectorService);

这将返回一个Future&lt;Collection&gt;。但是我们不想再使用 future 并且需要 CompletableFuture 。一个想法是我们不需要使用 CompletableFuture 进行轮询,也不需要等待和阻塞,直到它准备好。

那么当callable 线程完成时,我将如何使用可完成的未来并调用一个函数说isDone()

【问题讨论】:

  • “我们不想再使用future,需要CompletableFuture”——“想要”和“需要”的有趣组合。对我来说这听起来不是一个理性的决定……
  • @Holger :同意你的看法。应该改写我的话。我们已经实现了 Future,但似乎使用我们代码的团队不想对 Future.isDone() 进行轮询,因此希望我们提供 CompletableFuture

标签: java multithreading java-8 future completable-future


【解决方案1】:

给定CompletableFuture&lt;T&gt; f,您可以使用以下方法启动同步或异步任务以在完成后运行:

f.thenApply(result -> isDone(result));      // sync callback
f.thenApplyAsync(result -> isDone(result)); // async callback

...或者,如果您不需要结果:

f.thenRun(() -> isDone());
f.thenRunAsync(() -> isDone());

【讨论】:

  • 很抱歉询问更多,但我如何在 thenApply 函数中提交我的 Executor 类对象。结果对象在这里指的是什么?
  • 传递给thenAccept[Async]Consumer&lt;T&gt;是对任务结果进行操作的回调,所以result指的是未来f的结果。在您的原始示例中,它将是Collection。如果您想在回调中提交另一个任务,您可以从回调 lamda 引用任何 final(或“有效最终”)引用,包括您的执行者。
  • thenApply 也是异步的,XXXAsync 方法意味着在不同的线程中执行。
【解决方案2】:

您可以创建一个调用现有 collectorService 的 lambda 表达式。 CompletableFuture.supplyAsync 将接受的供应商 lambda 表达式看起来像这样

 Supplier<Collection> supplier = () -> collectorService.call();

并且可以和 CompletableFuture 一起使用如下

  CompletableFuture.supplyAsync(() -> collectorService.call(),service)
         .thenApply(collection->isDone(collection);

正如其他人指出的那样,thenApply 将在 collectorService.call() 方法返回结果时执行 - 在执行 Future 任务的同一线程上。使用 thenApplyAsync 会将另一个任务重新提交给执行器服务(原始性能大约要慢一个数量级,因此除非您也有充分的理由,否则不要这样做!)。

【讨论】:

    【解决方案3】:

    如果我对您的理解正确,您想知道如何提交返回 CompletableFuture 的“任务”(您以前的“执行者”)。

    你可以通过调用来做到这一点

    CompletableFuture.supplyAsync(collectorService)
    

    不同之处在于你的“Executor”现在必须实现 Supplier 而不是 Callable

    【讨论】:

    • 是的,如果不能选择更改源,collectorService 也可以包装在 Supplier lambda 表达式中。例如CompletableFuture.supplyAsync(() -> collectorService.call())
    • @JohnMcClean 我认为您的评论是最好的答案,我认为您应该将其作为实际答案。
    • @aalku 当然,添加了一个更详细的具体答案。
    【解决方案4】:

    我们不会在 completableFuture 中传递 runnable 或 callable。它采用供应商类型,这是一个功能接口。只需创建普通方法并将它们与执行器对象一起传递。参考下面的例子。

    package completableFuture;
    
    import java.util.Random;
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class CompFuture {
        ExecutorService firstExecService = Executors.newFixedThreadPool(5);
    
        public static void main(String[] args) {
    
            CompFuture compFuture = new CompFuture();
            compFuture.testMe("Java");
        }
    
        public String m1(String param) {
    
            Random r = new Random();
            int val = r.nextInt(20) * 1000;
            System.out.println(Thread.currentThread().getName() + " " + val);
    
            try {
                Thread.sleep(val);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return param + " Hello my";
        }
    
        public void m2(String salutation) {
            System.out.println(Thread.currentThread().getName() + "  ##" + salutation + " Friend!");
        }
    
        public void testMe(String start) {
            System.out.println("TM: " + Thread.currentThread());
    
            for (int i = 0; i < 5; i++) {
                CompletableFuture.supplyAsync(() -> m1(start), firstExecService).thenAccept(s -> m2(s));
            }
        }
    
    }
    

    上述程序的输出:: 执行时间最短的线程首先给出它的输出。

    TM: 线程[main,5,main]

    pool-1-thread-1 1000

    pool-1-thread-2 14000

    pool-1-thread-4 3000

    pool-1-thread-3 0

    pool-1-thread-5 9000

    pool-1-thread-3 ##Java 你好,我的朋友!

    pool-1-thread-1 ##Java 你好,我的朋友!

    pool-1-thread-4 ##Java 你好,我的朋友!

    pool-1-thread-5 ##Java 你好,我的朋友!

    pool-1-thread-2 ##Java 你好,我的朋友!

    【讨论】:

      猜你喜欢
      • 2014-06-12
      • 2021-08-03
      • 2022-06-13
      • 2023-02-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多