我想将此线性循环转换为并发循环:
for(Item item : ItemList) {
processItem(item);
}
这真的是最短的方式吗?
class Worker implements Runnable {
Item item;
Worker(Item item) {
this.item = item;
}
public void Run() {
processItem(item);
}
}
ExecutorService exec = Executors.newFixedThreadPool(THREADPOOL_SIZE);
for(Item item : ItemList) {
exec.execute(new Worker(item));
}
exec.shutdown();
boolean properFinish = false;
try {
properFinish = exec.awaitTermination(50, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
具体来说,我想要一种使用匿名类的方法,但实际上,任何使这种更短且更易读的方法都会受到赞赏。
更新:刚刚意识到我有点愚蠢,因为在这个例子中使用匿名类非常容易:
for(final Item item : ItemList) {
exec.execute(new Runnable() {
public void run() {
processItem(item);
}
});
}
在我的原始代码中,循环是一个简单的for (i=0; i<=ItemList.length(); i++)
,我无法想出以任何有意义的方式使我成为最终的方法。我想使用“for each”循环可以使情况更好。
还是,还有什么方法可以摆脱其余的样板吗?
更新2 :使用ExecutorCompletionService
,假设processItem
返回结果。
ExecutorService exec = Executors.newFixedThreadPool(THREADPOOL_SIZE);
CompletionService<ResultType> ecs = new ExecutorCompletionService<ResultType>(executor);
for(final Item item : ItemList) {
ecs.submit(new Callable<ResultType>() {
public ResultType call() {
return processItem(item);
}
});
}
for(Item item : item) {
// Do whatever with the results
ecs.take().get();
}
这确实看起来更好。
答案 0 :(得分:7)
查看JDK 6中的 ExecutorCompletionService - 而不是旋转自己的。它允许您为分配的任务执行多个线程,并在处理时获取每个线程的结果。
答案 1 :(得分:1)
如果您确实需要结果,并希望它们与提交的顺序相同,那么可能会执行以下操作:
List<Future<ResultType>> futures = new ArrayList<Future<ResultType>>();
for(final Item item : items) {
futures.add(executor.submit(...))
}
List<ResultType> results = new ArrayList<ResultType>();
for(Future<ResultType> future : futures) {
results.add(future.get());
}
return results;
编辑:如果你有一些过度工程,你可以返回一个迭代器,而不是做第二个循环(这样调用者可以在所有可用之前开始处理结果):
return Iterators.transform(results, new Function<Future<ResultType>,ResultType>() {
public ResultType apply(Future<ResultType> future) {
return future.get();
}
})
使用google collection库中的“Iterators”。另一种可能性是返回Futures列表并让调用者等待。