我想编写一个测试,对我的API执行许多并行调用。
ExecutorService executor = Executors.newCachedThreadPool();
final int numOfUsers = 10;
for (int i = 0; i < numOfUsers; i++) {
executor.execute(() -> {
final Device device1 = getFirstDevice();
final ResponseDto responseDto = devicesServiceLocal.acquireDevice(device1.uuid, 4738);
if (responseDto.status == Status.SUCCESS)
{
successCount.incrementAndGet();
}
});
}
我知道我可以使用executorThreadsPool来完成它,就像这样:
devicesList.parallelStream()
.map(device -> do something)
我可以用java8并行流创建它:
我如何在一台设备上执行此操作?
意思是我很少想要获得相同的设备。
类似的东西:
{{device}}.parallelStream().execute(myAction).times(10)
答案 0 :(得分:1)
是的,但是......
你会想到
Stream.generate(() -> device)
.limit(10)
.parallel()
.forEach(device -> device.execute());
应该做的工作。但不,因为原因(我真的不知道为什么,没有线索)。
如果我让device.execute()
等一下,然后让它打印一些东西。流每秒打印10次。所以它并非完全平行,而不是你想要的。
谷歌是我的朋友,我发现很多文章都警告过parallelStream。但我的目光落在http://blog.jooq.org/2014/06/13/java-8-friday-10-subtle-mistakes-when-using-the-streams-api/ 8号和9号.8说如果它是由一个集合支持你必须对它进行排序,它会神奇地起作用:
Stream.generate(() -> device)
.limit(10)
.sorted((a,b)->0) // Sort it (kind of), what??
.parallel()
.forEach(device -> device.execute());
现在它在一秒钟后打印8次,在另一秒钟后打印2次。我有8个内核,所以我们(有点)期望。
我在我的信息流中使用了.forEach()
,但起初我(就像你的例子)使用.map()
。 .map()
没有打印出来的东西:流从未消耗过(参见链接文章中的9)。
因此,请注意使用流,尤其是并行流。你必须确保你的流被消耗,它是有限的(.limit()
),它是并行的,等等。流很奇怪,我建议保留你的工作解决方案。
注意:如果device.execute()
是一个阻止操作(IO,网络......),那么你将永远不会超过你的核心数量(在我的情况下为8个),这些任务将同时执行。< / p>
更新(感谢Holger):
霍尔格给出了一个优雅的选择:
IntStream.range(0,10)
.parallel()
.mapToObject(i -> getDevice())
.forEach(device -> device.execute());
// Or shorter:
IntStream.range(0,10)
.parallel()
.forEach(i -> getDevice().execute());
就像一个并行的for循环(它可以工作)。