Java Streams基于硬件上的并行数量。但是如果我想要始终拥有最大的并行度呢?
请考虑以下代码。我希望10个任务中的每个任务同时运行100毫秒。
long runUntil = System.currentTimeMillis() + 100;
IntStream.range(0, 10).parallel().forEach(i ->
{
int cnt = 0;
while(System.currentTimeMillis() < runUntil)
cnt++;
System.out.println(i + ": " + cnt);
});
然而,我得到的结果是:
2: 56443
1: 67506
4: 74693
6: 70549
0: 0
3: 0
5: 0
7: 0
8: 0
9: 0
因此,只有4个任务并行执行,第五个任务仅在前4个任务中的一个完成时开始。我希望所有任务大约在同一时间开始,而不是等待彼此。
我不同意它是Custom thread pool in Java 8 parallel stream的副本,因为这个问题是关于阻止其他任务的慢速运行任务,而在我的情况下,我只是想知道如何(如果可以)最大化使用Stream API时的并行性。
答案 0 :(得分:5)
执行并行流时,您可以调用ForkJoinPool,该池的工作线程数等于以下结果:
Runtime.getRuntime().availableProcessors(); // 4 in your case
所以并行任务由4个线程同时执行。
当你开始第5个任务时(已经过了100毫秒),所以这个条件:
while(System.currentTimeMillis() < runUntil)
报告错误,因此仅为零。
要解决此问题,您可以自己创建一个ForkJoinPool,如本答案中所述(https://stackoverflow.com/a/22269778/2947592)
long runUntil = System.currentTimeMillis() + 1000;
ForkJoinPool forkJoinPool = new ForkJoinPool(10); // 10 Threads
forkJoinPool.submit(() ->
IntStream.range(0, 10).parallel().forEach(i -> {
int cnt = 0;
while (System.currentTimeMillis() < runUntil)
cnt++;
System.out.println(i + ": " + cnt);
})).get();
答案 1 :(得分:1)
所以我已经找到了自己问题的答案。问题是,它真的感觉像一个黑客,而不是一个适当的解决方案。我不习惯在生产环境中使用它。
System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "10");
现在,当我让它运行1000毫秒时,我会得到这样的结果:
9: 40158551
8: 41835052
0: 39087202
4: 37993773
6: 37993442
7: 36503041
2: 40076207
1: 37894657
5: 35785211
3: 40086037
我认为我的要求是合理的,我很惊讶流API不支持它。