首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >CompletableFuture.get(超时)不应该终止任务吗?

CompletableFuture.get(超时)不应该终止任务吗?
EN

Stack Overflow用户
提问于 2022-12-01 10:49:58
回答 2查看 49关注 0票数 0

我正在运行两个CompletableFuture实例,等待1秒,然后将一些内容打印到控制台。第一次我在0.5秒后中断。所以我只希望第二张打印出来,但事实上两者都是。这里发生了什么事?

下面是代码:

代码语言:javascript
运行
复制
CompletableFuture<Void> c1 = CompletableFuture.runAsync(() -> {
    System.out.println("Start CF 1");
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    System.out.println(1);
});

CompletableFuture<Void> c2 = CompletableFuture.runAsync(() -> {
    System.out.println("Start CF 2");
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    System.out.println(2);
});

long start = System.currentTimeMillis();
try {
    c1.get(500, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
    System.out.println("CF interrupted after " + (System.currentTimeMillis() - start) + "ms");
}
c2.get();

印出来:

代码语言:javascript
运行
复制
Start CF 1
Start CF 2
CF interrupted after 510ms
2
1
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-12-01 11:21:35

你为什么认为应该这样?如果两个消费者想要处理同一个未来的结果,而其中一个准备等待的时间比另一个长呢?第一种可能会在第二种情况下杀死它,这可能是它及时完成的。

在任何情况下,Java都没有杀死任务的概念。您能做的最好是设置一个标志,要求它停止--一个中断--但是这依赖于任务检查和尊重标志。您的任务是这样做的,因为Thread.sleep()隐式地检查中断标志,但这是一个人为的例子,很多任务都不会检查它。

票数 1
EN

Stack Overflow用户

发布于 2022-12-01 12:04:55

get方法的超时只说明何时应该停止get方法的执行。它不影响计算结果。这适用于所有未来。

因此,要中断任务,您需要调用cancel(true),但in case of CompletableFuture甚至不会中断任务:

参数:

  • mayInterruptIfRunning -此值在此实现中没有任何影响,因为中断不用于控制处理。

如果需要可中断任务,则需要使用ExecutorService,但也可以使用与CompletableFuture的默认执行器相同的线程池:

代码语言:javascript
运行
复制
public static void main(String[] args) throws InterruptedException, ExecutionException {
    ExecutorService es = ForkJoinPool.commonPool();
    Future<Void> c1 = es.submit(() -> {
        System.out.println("Start CF 1");
        Thread.sleep(1000);
        System.out.println(1);
        return null;
    });

    Future<Void> c2 = es.submit(() -> {
        System.out.println("Start CF 2");
        Thread.sleep(1000);
        System.out.println(2);
        return null;
    });

    long start = System.currentTimeMillis();
    try {
        c1.get(500, TimeUnit.MILLISECONDS);
    } catch(TimeoutException e) {
        c1.cancel(true);
        System.out.println("timeout after "
                + (System.currentTimeMillis() - start) + "ms, canceled");
    }
    c2.get();
}

请注意,中断可能仍然太慢,无法阻止1的打印。在我的机器上,我至少需要Thread.sleep(1100);来中断打印前的任务。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74640683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档