2009-05-27 99 views
3

我想這種線性循環轉換成並行之一:讓它非常:處理數組同時

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(); 
} 

具體來說,我想辦法使用匿名類,但實際上,沒有辦法讓這個短更易讀,將不勝感激。

UPDATE:剛剛意識到我是一個有點傻,因爲它很容易在這個例子中使用匿名類:

for(final Item item : ItemList) { 
    exec.execute(new Runnable() { 
     public void run() { 
      processItem(item); 
     } 
    }); 
} 

在我的原代碼,循環是一個簡單的for (i=0; i<=ItemList.length(); i++)和我想不到以任何合理的方式讓我成爲最後的一種方式。我想用「爲每個」循環使情況更好。

還有,如何擺脫樣板的其餘部分?

UPDATE 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

謹慎的話,上面的代碼可能會死鎖,如果由於某種原因,你的一個線程不會返回。您可能希望使用輪詢(長時間超時,TimeUnit單位)來代替。 – Gandalf 2009-05-27 15:44:19

回答

7

查看JDK 6中的ExecutorCompletionService - 而不是旋轉自己的。它允許您爲分配的任務執行多個線程,並獲取每個線程處理結果。

+3

ExecutorCompletionService也在JDK5中。 – Thilo 2009-05-27 07:26:36

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(); 
    } 
}) 

:不要做第二個循環(這樣,來電者就可以開始處理結果所有可用之前)。另一種可能性是隻返回期貨清單並讓來電者等待。