Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java CompletableFuture.allOff完成,即使其列表中的一个CompletableFuture尚未完成_Java_Asynchronous_Completable Future - Fatal编程技术网

Java CompletableFuture.allOff完成,即使其列表中的一个CompletableFuture尚未完成

Java CompletableFuture.allOff完成,即使其列表中的一个CompletableFuture尚未完成,java,asynchronous,completable-future,Java,Asynchronous,Completable Future,我有两个完整的未来。task2只能在task1完成后启动。然后,我需要等待所有任务完成。在我下面的代码中,程序在task1结束后结束。task2已启动,但未完成。你知道为什么会这样吗?另外,为什么列表只包含1个条目,而在代码中,我添加了2个条目 代码: 你有两个问题 首先,您已经创建了一个竞赛条件,以确定task2何时被添加到您的未来列表中。在执行这一行时- CompletableFuture.allOf(...).get(); -我称之为终止getter,列表中只有task1。通过输出其大小

我有两个完整的未来。task2只能在task1完成后启动。然后,我需要等待所有任务完成。在我下面的代码中,程序在task1结束后结束。task2已启动,但未完成。你知道为什么会这样吗?另外,为什么列表只包含1个条目,而在代码中,我添加了2个条目

代码:

你有两个问题

首先,您已经创建了一个竞赛条件,以确定task2何时被添加到您的未来列表中。在执行这一行时-

CompletableFuture.allOf(...).get();
-我称之为终止getter,列表中只有task1。通过输出其大小自己查看:

// wait for the calls to finish
try {
    System.out.println("# of futures: " + futures.size()); // 1
task2最终仍会运行,因为您计划了whenComplete。但触发它的不是你的终止getter

记得我说过这是比赛条件。为了亲自演示这一点,请在终止getter之前添加一个sleep,如下所示:

try {
  Thread.sleep(6000L);
} catch (InterruptedException ex) {
  ex.printStackTrace();
}
// wait for the calls to finish
try {
    System.out.println("# of futures: " + futures.size()); // 2
那么您就有足够的时间添加task2了

但事情是这样的。现在终止getter是否同时触发这两个任务

还是不行!这就是第二个问题:您几乎总是希望使用一个thenRun、thenAccept、thenApply和thenCompose方法。这些方法链接您的未来,即使每个阶段依赖于前一个阶段,以便您的终止getter实际等待整个链完成。whenComplete是一种特殊方法,它启动一个完全无关的管道,因此不受终止get的影响

在您的情况下,您希望使用thenRun,如下所示:

    task1.thenRun( ignore -> {
好吧,那我们怎么把这些结合起来呢

public static void testFutures () throws Exception {
    
    CompletableFuture<Void> task1 = CompletableFuture.supplyAsync( () -> {
      System.out.println(" task1 start");
      try {
        Thread.sleep(5000L);
      } catch (InterruptedException ex) {
        ex.printStackTrace();
      }
      System.out.println(" task1 done");
      return null;
    });

    CompletableFuture<Void> futuresChain = task1.thenRun( () -> {
      System.out.println(" task2 start");
      try {
        Thread.sleep(2000L);
      } catch (InterruptedException ex) {
        ex.printStackTrace();
      }
      System.out.println(" task2 done");
    });
    
    // wait for the calls to finish
    try {
      futuresChain.thenRun( () -> {
        System.out.println(" all tasks done ");
      }).toCompletableFuture().get();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

你看,你只需要为第一个任务提供同步。您希望在该任务之后按顺序运行task2,因此run将为您安排供应同步。所以你也不需要一系列的期货。allOf用于并行运行任务,并等待所有任务完成。

让我们首先清理代码

让我们定义一种睡眠方法,这样就不会弄脏水:

private static void sleep(int seconds) {
    try {
        Thread.sleep(TimeUnit.SECONDS.toMillis(seconds));
    } catch (InterruptedException ex) {
        throw new RuntimeException(ex);
    }
}
然后,让我们将任务分开,并使用适当的方法:

private static CompletableFuture<Void> task1() {

    return CompletableFuture.runAsync(() -> {
        System.out.println(" task1 start");
        sleep(5);
        System.out.println(" task1 done");
    });
}

private static CompletableFuture<Void> task2() {
    return CompletableFuture.runAsync(() -> {
        System.out.println(" task2 start");
        sleep(2);
        System.out.println(" task2 done");
    });
}

这对于这么简单的任务来说太复杂了。@Eugene-嗯,我的答案建立在学生目前的理解基础上,即使不完善。你的答案显示了理想的目的地。两者都很好。
 task1 start
 task1 done
 task2 start
 task2 done
 all tasks done 
private static void sleep(int seconds) {
    try {
        Thread.sleep(TimeUnit.SECONDS.toMillis(seconds));
    } catch (InterruptedException ex) {
        throw new RuntimeException(ex);
    }
}
private static CompletableFuture<Void> task1() {

    return CompletableFuture.runAsync(() -> {
        System.out.println(" task1 start");
        sleep(5);
        System.out.println(" task1 done");
    });
}

private static CompletableFuture<Void> task2() {
    return CompletableFuture.runAsync(() -> {
        System.out.println(" task2 start");
        sleep(2);
        System.out.println(" task2 done");
    });
}
public static void main(String[] args) throws Exception {
    testFutures();
}

private static void testFutures() throws Exception {

    CompletableFuture<Void> both = task1().thenCompose(ignoreMe -> task2());
    both.get();
    System.out.println("both done");

}