为什么CompletableFuture.supplyAsync成功随机次数? [英] Why is CompletableFuture.supplyAsync succeeding a random number of times?
问题描述
我是Java 8中的lambdas和异步代码的新手。我不断得到一些奇怪的结果......
I'm new to both lambdas and asynchronous code in Java 8. I keep getting some weird results...
我有以下代码:
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服务。但是,我能用这个简单的代码复制我的问题。
The actual code is a lot longer, as the doPost
method will post some data to a web service. However, I'm able to replicate my issue with this bare-bones code.
我想要 doPost
方法执行100次,但出于性能原因异步(为了将数据推送到Web服务的速度比执行100次同步调用的速度快)。
I want to have the doPost
method execute 100 times, but asynchronously for performance reasons (in order to push data to the web service faster than doing 100 synchronous calls would be).
在上面的代码中,'doPost'方法是随机运行的,但总是不超过20-25次。没有异常抛出。似乎某些线程处理机制默默地拒绝创建新线程并执行它们的代码,或者线程在没有崩溃程序的情况下静默崩溃。
In the code above, the ´doPost´ method is run a random amount of times, but always no more than 20-25 times. There are no exceptions thrown. It seems that either some thread handling mechanism is silently refusing to create new threads and execute their code, or the threads are silently crashing without crashing the program.
我也有一个问题在于,如果我向 doPost
方法添加比上面显示的更多的功能,它会达到方法只是默默地中断的程度。在这种情况下,我尝试在return语句之前添加一个 System.out.println(test)
,但它永远不会被调用。循环100次的循环确实运行了100次迭代。
I also have an issue where, if I add more functionality to the doPost
method than shown above, it reaches a point where the method simply silently breaks. I've tried adding a System.out.println("test")
right before the return statement in that case, but it is never called. The loop which loops 100 times does run 100 iterations though.
这种行为令人困惑,至少可以说。
This behaviour is confusing, to say the least.
我错过了什么?为什么作为参数提供的函数 supplyAsync
运行一个看似随机的次数?
What am I missing? Why is the function supplied as an argument to supplyAsync
run a seemingly random number of times?
编辑:只是想指出情况与问题中的情况不完全相同,因为这个问题涉及任意深度嵌套的期货,而这一问题涉及平行的问题。然而,他们失败的原因几乎完全相同。案件看起来很明显,值得我提出不同的问题,但其他人可能不同意......
推荐答案
默认情况下 CompletableFuture
使用自己的 ForkJoinPool.commonPool()(参见 CompletableFuture
实现)。此默认池仅创建守护程序线程,例如他们不会阻止主要应用程序终止,如果他们还活着。
By default CompletableFuture
uses own ForkJoinPool.commonPool() (see CompletableFuture
implementation). And this default pool creates only daemon threads, e.g. they won't block the main application from terminating if they still alive.
您有以下选择:
-
收集所有
CompletionStage
到某个数组然后makejava.util.concurrent.CompletableFuture #allOf()
.toCompletableFuture()。join()
- 这将保证所有阶段完成后再继续 join()
Collect all
CompletionStage
to some array and then makejava.util.concurrent.CompletableFuture#allOf()
.toCompletableFuture().join()
- this will guarantee all the stages are completed before going after join()
对您自己的线程池使用 * Async 操作,该线程池仅包含非守护进程线程,如下例所示:
Use *Async operations with your own thread pool which contains only non-daemon threads, like in the following example:
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;
}
这篇关于为什么CompletableFuture.supplyAsync成功随机次数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!