2011-10-13 72 views

回答

19

假設你有一組任務A, B, C, D, E的幾個例子,你想在Executor異步執行它們各自和處理結果1 1,因爲他們完成。

隨着Executor,你會做這樣這樣的:

List<Future<?>> futures = new ArrayList<Future<?>>(); 
futures.add(executorService.submit(A)); 
futures.add(executorService.submit(B)); 
futures.add(executorService.submit(C)); 
futures.add(executorService.submit(D)); 
futures.add(executorService.submit(E)); 

//This loop must process the tasks in the order they were submitted: A, B, C, D, E 
for (Future<?> future:futures) { 
    ? result = future.get(); 
    // Some processing here 
} 

這種方法的問題是,有沒有保證,任務A將首先完成。因此,當主線程可能正在處理另一個任務(例如任務B)的結果時,主線程可能會空閒阻塞等待任務A完成。通過使用ExecutorCompletionService可以減少結果處理等待時間。

List<Future<?>> futures = new ArrayList<Future<?>>(); 
futures.add(executorCompletionService.submit(A)); 
futures.add(executorCompletionService.submit(B)); 
futures.add(executorCompletionService.submit(C)); 
futures.add(executorCompletionService.submit(D)); 
futures.add(executorCompletionService.submit(E)); 

//This for loop will process the tasks in the order they are completed, 
//regardless of submission order 
for (int i=0; i<futures.size(); i++) { 
    ? result = executorCompletionService.take().get(); 
    // Some processing here 
} 

因此,在本質上,ExecutorCompletionService可用於擠出多一點效率時的處理任務結果的順序並不重要。

但要注意的一點很重要。 ExecutorCompletionService的實現包含一個結果隊列。如果不調用takepoll來排空該隊列,則會發生內存泄漏。有些人使用submit返回的Future來處理結果,這是不正確的用法。

+0

正確的用法只是爲了自己創造未來;) – bestsss

+1

非常感謝Tim的支持。這個例子和解釋很清楚。 –

+0

這樣一個驚人的答案,到目前爲止只有18票。這讓我難過。那個嬰兒看起來很可愛在你的手中。 –