2013-07-02 66 views
6

我通過將Callable s提交到Executor創建了一組Futures。僞代碼:等待一批期貨完成時超時?

for all tasks 
    futures.add(executor.submit(new callable(task))) 

現在我想讓所有期貨最多等待n秒,直到全部完成。我知道我可以打電話給Future#get(timeout),但是如果我按順序爲我的所有期貨在循環中調用,那麼時間開始加起來。僞代碼:

for all futures 
    future.get(timeout) 

get塊以超時,直到結果已經準備就緒。因此,如果第一個在超時之前完成,第二個也在超時之前完成,那麼整個執行時間至多爲number of futures * timeout而不是timeout

因此,我正在尋找一種方法,它接受Future的列表和超時,並行運行,然後返回未來結果的集合。有任何想法嗎?

+0

這並不完全清楚。當超時到期時,你想要發生什麼還沒有完成的任務?你希望他們被取消還是被允許繼續? –

+0

他們應該被取消。另外,不知何故,我需要知道哪些已完成,哪些沒有完成。我想因爲我可以在期貨上重複一遍,並在所有期貨上調用'isDone'。 –

回答

5

您可以使用ExecutorService.invokeAll

執行給定的任務,返回保持狀態期貨和結果的列表時,所有任務完成或超時期滿時,先發生者爲準。 Future.isDone()對於返回列表的每個元素都是true。返回後,尚未完成的任務將被取消。請注意,完成的任務可能正常結束或通過拋出異常終止。如果在進行此操作時修改了給定集合,則此方法的結果未定義。


如果你已經有Future是你們等需要監控和不能使用invokeAll,你可以簡單地衡量自己的超時。僞代碼:

long endTime = System.currentTimeMillis() + timeoutMS; 
for(f : futures) 
    f.get(Math.max(0, endTime - System.currentTimeMillis()), TimeUnit.MILLISECONDS); 

這樣,您最多可以給出每個未來的持續時間,直到您到達超時。

+0

'ExecutorService.invokeAll'聽起來像我之後,謝謝。對於所有未及時完成的​​期貨'isCancelled == true',對(我如何解釋Javadoc)?我將如何查明「Future」是否完成,但有異常? 「請注意,完成的任務可能正常結束或通過拋出異常終止」 - 這很難... –

+1

@MarcelStör是的,未完成的期貨將被取消('isCancelled()== true')。然後,當您將其稱爲['get()']時,您可以確定'Future'發生了什麼事情(http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html#得到%28%29)(在'invokeAll'返回之後)。如果'get'拋出'CancellationException',你知道它已被取消。如果它引發'ExecutionException',則意味着未來完成了一個異常,並且可以通過'ExecutionException.getCause()'來訪問異常。 –