gpt4 book ai didi

java - 为什么 CompletableFuture.supplyAsync 会成功随机次数?

转载 作者:行者123 更新时间:2023-12-01 20:55:25 29 4
gpt4 key购买 nike

我对 Java 8 中的 lambda 表达式和异步代码都很陌生。我不断得到一些奇怪的结果...

我有以下代码:

import java.util.concurrent.CompletableFuture;

public class Program {

public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
String test = "Test_" + i;
final int a = i;

CompletableFuture<Boolean> cf = CompletableFuture.supplyAsync(() -> doPost(test));
cf.thenRun(() -> System.out.println(a)) ;
}
}

private static boolean doPost(String t) {
System.out.println(t);

return true;
}
}

实际代码要长得多,因为 doPost 方法会将一些数据发布到 Web 服务。不过,我可以用这个简单的代码来复制我的问题。

我想让 doPost 方法执行 100 次,但出于性能原因而异步执行(以便比执行 100 次同步调用更快地将数据推送到 Web 服务)。

在上面的代码中,“doPost”方法运行随机次数,但始终不超过 20-25 次。没有抛出异常。似乎某些线程处理机制默默地拒绝创建新线程并执行其代码,或者线程默默地崩溃而不会导致程序崩溃。

我还有一个问题,如果我向 doPost 方法添加比上面显示的更多的功能,它就会达到该方法只是默默地中断的地步。在这种情况下,我尝试在 return 语句之前添加一个 System.out.println("test") ,但它从未被调用。不过,循环 100 次的循环确实运行了 100 次迭代。

至少可以说,这种行为令人困惑。

我错过了什么?为什么作为 supplyAsync 参数提供的函数运行看似随机的次数?

编辑:只是想指出,情况与被标记为可能重复的问题并不完全相同,因为该问题涉及任意深度嵌套的 future ,而这个问题涉及并行那些。然而,他们失败的原因几乎是相同的。这些案例似乎足够明显,值得我单独提出问题,但其他人可能不同意......

最佳答案

默认情况下,CompletableFuture 使用自己的ForkJoinPool.commonPool()(请参阅 CompletableFuture 实现)。这个默认池仅创建守护进程线程,例如如果它们还活着,它们不会阻止主应用程序终止。

您有以下选择:

  1. 将所有 CompletionStage 收集到某个数组,然后制作 java.util.concurrent.CompletableFuture#allOf() .toCompletableFuture().join() - 这将保证在join()

  2. 之后完成所有阶段
  3. *异步操作与您自己的线程池一起使用,该线程池仅包含非守护程序线程,如以下示例所示:

    public static void main(String[] args) throws InterruptedException {
    ExecutorService pool = Executors.newFixedThreadPool(10, r -> {
    Thread t = new Thread(r);
    t.setDaemon(false); // must be not daemon
    return t;
    });

    for (int i = 0; i < 100; i++) {
    final int a = i;

    // the operation must be Async with our thread pool
    CompletableFuture<Boolean> cf = CompletableFuture.supplyAsync(() -> doPost(a), pool);
    cf.thenRun(() -> System.out.printf("%s: Run_%s%n", Thread.currentThread().getName(), a));
    }

    pool.shutdown(); // without this the main application will be blocked forever
    }

    private static boolean doPost(int t) {
    System.out.printf("%s: Post_%s%n", Thread.currentThread().getName(), t);

    return true;
    }

关于java - 为什么 CompletableFuture.supplyAsync 会成功随机次数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42439198/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com