为什么打电话之前完成特殊的等待格外执行get()方法?

迪迪埃·L:

在回答这个问题,我注意到一个奇怪的现象CompletableFuture:如果你有一个CompletableFuture cf和链的呼叫cf.exceptionally(),呼叫cf.get()出现运行异常:

  • 如果你非凡完成之前调用它,它等待的执行exceptionally()块返回前
  • 否则,就通过抛出预期立即失败 ExecutionException

我缺少的东西,或这是一个错误?我在Ubuntu 17.04使用Oracle JDK 1.8.0_131。

下面的代码说明了这一现象:

public static void main(String[] args) {
    long start = System.currentTimeMillis();
    final CompletableFuture<Object> future = CompletableFuture.supplyAsync(() -> {
        sleep(1000);
        throw new RuntimeException("First");
    }).thenApply(Function.identity());

    future.exceptionally(e -> {
        sleep(1000);
        logDuration(start, "Exceptionally");
        return null;
    });

    final CompletableFuture<Void> futureA = CompletableFuture.runAsync(() -> {
        try {
            future.get();
        } catch (Exception e) {
        } finally {
            logDuration(start, "A");
        }
    });

    final CompletableFuture<Void> futureB = CompletableFuture.runAsync(() -> {
        sleep(1100);
        try {
            future.get();
        } catch (Exception e) {
        } finally {
            logDuration(start, "B");
        }
    });

    try {
        future.join();
    } catch (Exception e) {
        logDuration(start, "Main");
    }

    futureA.join();
    futureB.join();
}

private static void sleep(final int millis) {
    try {
        Thread.sleep(millis);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}

private static void logDuration(long start, String who) {
    System.out.println(who + " waited for " + (System.currentTimeMillis() - start) + "ms");
}

输出:

B waited for 1347ms
Exceptionally waited for 2230ms
Main waited for 2230ms
A waited for 2230ms

正如你所看到的,futureB这之前调用睡一点get()都不会阻止。然而,无论是futureA和主线程等待exceptionally()完成。

请注意,如果您删除此行为不会发生.thenApply(Function.identity())

霍尔格:

唤醒休眠的线程是具有像任何其他要处理的依赖性作用,它不具有优先级。在另一方面,一个线程轮询CompletableFuture时,它已经完成不会进入睡眠状态,没有必要被唤醒,因此,没有必要竞争与其他相关行动。

与以下程序

public static void main(String[] args) {
    final CompletableFuture<Object> future = CompletableFuture.supplyAsync(() -> {
        waitAndLog("Supplier", null, 1000);
        throw new RuntimeException("First");
    }).thenApply(Function.identity());
    long start = System.nanoTime();

    CompletableFuture.runAsync(() -> waitAndLog("A", future, 0));

    LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(10));

    future.exceptionally(e -> {
        waitAndLog("Exceptionally", null, 1000);
        return null;
    });

    CompletableFuture.runAsync(() -> waitAndLog("B", future, 0));
    CompletableFuture.runAsync(() -> waitAndLog("C", future, 1100));

    waitAndLog("Main", future, 0);
    ForkJoinPool.commonPool().awaitQuiescence(10, TimeUnit.SECONDS);
}
private static void waitAndLog(String msg, CompletableFuture<?> primary, int sleep) {
    long nanoTime = System.nanoTime();
    Object result;
    try {
        if(sleep>0) Thread.sleep(sleep);
        result = primary!=null? primary.get(): null;
    } catch (InterruptedException|ExecutionException ex) {
        result = ex;
    }
    long millis=TimeUnit.NANOSECONDS.toMillis(System.nanoTime()-nanoTime);
    System.out.println(msg+" waited for "+millis+"ms"+(result!=null? ", got "+result: ""));
}

我得到的,

Supplier waited for 993ms
A waited for 993ms, got java.util.concurrent.ExecutionException: java.lang.RuntimeException: First
C waited for 1108ms, got java.util.concurrent.ExecutionException: java.lang.RuntimeException: First
Exceptionally waited for 998ms
Main waited for 1983ms, got java.util.concurrent.ExecutionException: java.lang.RuntimeException: First
B waited for 1984ms, got java.util.concurrent.ExecutionException: java.lang.RuntimeException: First

我的机器上,这表明在这个特定的情况下,相关的行动是对的,他们在原定的顺序执行A第一。请注意,我插入额外的等待时间调度之前Exceptionally,这将是未来相关的动作。由于B在后台线程运行时,它是不确定性是否管理之前安排自己Main的线程或不。我们可以在前面插入另一延迟强制执行命令。

由于C民意调查已完成的未来,它可以立即进行,因此其净等待时间接近明确指定的睡眠时间。

必须强调的是,这是一个特别的情景只有结果,依赖于实现细节。有没有保证相关的操作,执行顺序。正如你可能已经注意到自己,没有.thenApply(Function.identity())一步,实施运行,导致有关动作的不同执行顺序不同的代码路径。

的依赖性形成树和实现必须遍历它以有效的方式,而不用担心堆栈溢出,因此它具有以某种方式与小的变化,以将其压平的依赖关系树中的非可影响所得到的顺序的形状直观的方式。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Main方法等待执行中的线程完成。为什么?

来自分类Dev

在start方法停止之前,等待函数完成执行

来自分类Dev

为什么我的异步方法在执行调用方方法的下一行之前完成?

来自分类Dev

为什么我们不能打电话给setTimeout申请?

来自分类Dev

为什么我不能直接打电话给减速机?

来自分类Dev

为什么passport.authenticate不打电话?

来自分类Dev

为什么在 forEach 循环完成之前执行代码?

来自分类Dev

方法返回完成执行之前?

来自分类Dev

jQuery在执行之前的事件之前等待for循环完成

来自分类Dev

Golang,打电话给父母的方法

来自分类Java

为什么主线程在继续之前要等待另一个线程完成?

来自分类Dev

为什么在我的代码通过等待命令之前此任务未完成

来自分类Dev

java-为什么在执行下一行之前完成线程执行

来自分类Dev

在设置值之前等待方法完成

来自分类Dev

在继续之前等待 axios 的方法完成

来自分类Dev

在继续 Angular 之前等待方法完成

来自分类Dev

为什么等待不能确保方法中的执行顺序?

来自分类Dev

为什么要在创建项目之前执行返回,然后console.log等待并显示正确的ID?

来自分类Dev

在调用函数之前等待 API 调用完成的正确方法是什么

来自分类Dev

在 puppeteer 中再次执行之前等待操作完成

来自分类Dev

在执行另一个之前等待 SwingWorker 完成

来自分类Dev

在执行下一行代码之前等待超时完成

来自分类Dev

SwiftUI:在执行以下代码之前等待 Alamofire 请求完成

来自分类Dev

为什么componentWillReceiveProps()不等待setState()完成?

来自分类Java

为什么我越来越流<OBJECT>当我打电话后付费的流()()?

来自分类Dev

为什么打电话给我时,tkinter消息框没有显示?

来自分类Dev

为什么在kotlin(或java)中线程完成睡眠之前异常抛出执行

来自分类Dev

为什么Jest在componentDidMount完成执行之前(使用React Test Renderer)运行断言?

来自分类Dev

为什么在python脚本完成之前不执行打印作业?

Related 相关文章

  1. 1

    Main方法等待执行中的线程完成。为什么?

  2. 2

    在start方法停止之前,等待函数完成执行

  3. 3

    为什么我的异步方法在执行调用方方法的下一行之前完成?

  4. 4

    为什么我们不能打电话给setTimeout申请?

  5. 5

    为什么我不能直接打电话给减速机?

  6. 6

    为什么passport.authenticate不打电话?

  7. 7

    为什么在 forEach 循环完成之前执行代码?

  8. 8

    方法返回完成执行之前?

  9. 9

    jQuery在执行之前的事件之前等待for循环完成

  10. 10

    Golang,打电话给父母的方法

  11. 11

    为什么主线程在继续之前要等待另一个线程完成?

  12. 12

    为什么在我的代码通过等待命令之前此任务未完成

  13. 13

    java-为什么在执行下一行之前完成线程执行

  14. 14

    在设置值之前等待方法完成

  15. 15

    在继续之前等待 axios 的方法完成

  16. 16

    在继续 Angular 之前等待方法完成

  17. 17

    为什么等待不能确保方法中的执行顺序?

  18. 18

    为什么要在创建项目之前执行返回,然后console.log等待并显示正确的ID?

  19. 19

    在调用函数之前等待 API 调用完成的正确方法是什么

  20. 20

    在 puppeteer 中再次执行之前等待操作完成

  21. 21

    在执行另一个之前等待 SwingWorker 完成

  22. 22

    在执行下一行代码之前等待超时完成

  23. 23

    SwiftUI:在执行以下代码之前等待 Alamofire 请求完成

  24. 24

    为什么componentWillReceiveProps()不等待setState()完成?

  25. 25

    为什么我越来越流<OBJECT>当我打电话后付费的流()()?

  26. 26

    为什么打电话给我时,tkinter消息框没有显示?

  27. 27

    为什么在kotlin(或java)中线程完成睡眠之前异常抛出执行

  28. 28

    为什么Jest在componentDidMount完成执行之前(使用React Test Renderer)运行断言?

  29. 29

    为什么在python脚本完成之前不执行打印作业?

热门标签

归档