2011-07-28 107 views
3

所以我有這段Java代碼,我需要在一堆項目上做一些工作。我決定將其並行化以獲得一些額外的提升,但我仍然使用ThreadPoolExecutor。問題是,我需要做的工作可以拋出異常...在ThreadPool中報告異常並關閉

現在我想關閉整個工作,一遇到錯誤就停下來,並報告回來,以便我可以處理它。在網上查看時,我發現通過ExecutorCompletionService和分析未來結果的正常方式。但是,當第一個錯誤出現時,這不會讓我關閉所有的東西,因爲沒有辦法根據哪個任務先完成循環...

所以我做了一些我認爲是相當黑客和我很好奇,如果有更好的方法來處理這個問題。我所做的是:

1)讓每個我將執行的Runnable都有一個可執行Throwable的字段。 2)覆蓋TPE的「afterExecute」方法,並檢查是否有任何檢查的異常被拋出(記錄在Runnable中)或任何未被檢查的異常被拋出(應該在此方法的第二個參數中報告)。如果有的話,我在TPE上發出shutdownNow()。

同樣,這似乎有點hacky,我想知道是否有什麼我失蹤。提前致謝!

+0

是否需要停止其他任務執行剛性測試,在第一次失敗後甚至執行單個測試是災難性的?或者它是一個「有益」的要求,因爲如果其他任務保持運行一段時間就可以了,但是越快它們停下來越好?我問,因爲即使說「第一次失敗來臨」在並行執行環境中也不清楚,因爲沒有仔細的同步,你不知道在不同線程上執行任務的順序。 –

+0

你明白了「很高興」的要求,因爲我只想通知所有並行任務,當他們中的一個遇到錯誤時應立即停止。當然,由於線程在池中運行的方式,這可能並不意味着「儘快」,但這是一個原則性的事情。 實際上,您可以將其視爲具有啓動我的ThreadPool的阻止調用,並且我希望這可以報告結果,如果一切正常,或儘快解除阻止以最大限度地提高可用性。 –

回答

2

ExecutorService.invokeAny

執行給定的任務,返回一個已成功完成(即未拋出異常)的結果,如果任何事情。在正常或異常返回時,尚未完成的任務將被取消。如果在進行此操作時修改了給定集合,則此方法的結果未定義。

它看起來確實和你想要做的事情完全相同......如果我正確理解你的問題。

但是,要取消任何操作,您必須讓您的Callable任務中斷。但是,無論您如何取消任務,這都適用。

編輯
這不是你所需要的;我誤解了javadoc。以下是另一種解決方案:您可以將所有Future列入清單,然後有一個半忙的while循環,您可以定期檢查每個futureList.get(i).get(100, TimeUnits.MILLISECONDS),您可以捕獲異常並採取相應的行動。然而,這不比你的解決方案更「優雅」。看起來afterExecute是爲了做你想做的。

+1

如果我的帖子誤解了,我表示歉意,但如果沒有遇到任何錯誤,我需要完成所有並行任務 - 這就是爲什麼我說我只是在線程之間分割工作。 invokeAny方法似乎在任何一個任務完成後立即返回,這符合「並行最佳結果計算」風格,而不是工作負載splittin ... –

+0

我誤解了javadoc。還有'invokeAll',但它似乎沒有以任何方式處理任務的異常。 – toto2

+0

@Bogdan看到我的編輯。 – toto2