我对 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
实现)。这个默认池仅创建守护进程线程,例如如果它们还活着,它们不会阻止主应用程序终止。
您有以下选择:
将所有
CompletionStage
收集到某个数组,然后制作java.util.concurrent.CompletableFuture#allOf()
.toCompletableFuture().join()
- 这将保证在join() 之后完成所有阶段
将*异步操作与您自己的线程池一起使用,该线程池仅包含非守护程序线程,如以下示例所示:
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/