我编写了这段代码,使用Executor.newFixedThreadPool和ConcurrentLinkedQueue同时构建一个对象集合。但是,我发现整个线程池和任务提交给它冗长。我希望我能用流更简洁地写出来。
private ConcurrentLinkedQueue<ApiRunner> getRunners(final ApiRunnerBuilder builder,
final int testSize) throws InterruptedException {
final ExecutorService executor = Executors.newFixedThreadPool(NUM_OF_CORES);
ConcurrentLinkedQueue<ApiRunner> runners = new ConcurrentLinkedQueue<ApiRunner>();
for (int i = 0; i < testSize; i++) {
executor.execute(() -> {
runners.add(builder.build());
});
}
executor.shutdown();
executor.awaitTermination(300, TimeUnit.SECONDS);
return runners;
}
我想也许它可以简化为这样的东西(java和java新手):
private ConcurrentLinkedQueue<ApiRunner> getRunners(final ApiRunnerBuilder builder,
final int testSize) throws InterruptedException {
ConcurrentLinkedQueue<ApiRunner> runners = new ConcurrentLinkedQueue<ApiRunner>();
ConcurrentLinkedQueue<ApiRunner> runners = range(testSize).parallelStream(()-> {
runners.add(builder.build());
});
}
return runners;
}
答案 0 :(得分:5)
既然你说过,你有很多I / O,我不建议使用流API。流API针对CPU绑定任务进行了优化,因为它根据CPU内核的数量调整线程数,但对于I / O绑定任务,当线程被阻塞等待完成时,可能会有更多的线程。 I / O操作不消耗CPU资源。
请注意,旧的API也适用于新的lambda表达式:
ExecutorService executor = Executors.newFixedThreadPool(DESIRED_CONCURRENCY);
ConcurrentLinkedQueue<ApiRunner> runners = new ConcurrentLinkedQueue<ApiRunner>();
executor.invokeAll(Collections.nCopies(testSize, ()->runners.add(builder.build())));
executor.shutdown();
return runners;
在实际应用程序中,您可能会使执行程序比此任务更长。方法invokeAll
已经等待所有任务的完成,因此这里既不需要关闭也不等待终止。 shutdown
调用仅在此示例中添加以进行清理,因为在这种情况下,您已在方法内部创建了执行程序。
答案 1 :(得分:4)
你可以这样做:
ConcurrentLinkedQueue<ApiRunner> runners =
Stream.generate(() -> builder.build())
.parallel()
.limit(testSize)
.collect(toCollection(ConcurrentLinkedQueue::new));