2011-10-25 14 views
2

線程我使用多個線程上做一個大的數據集的一些重(和出錯)的處理。我需要所有線程完成執行,無論它們是否拋出異常或正常終止(沒有返回值),在程序繼續之前。我正在使用CountDownLatch來實現此目的,並使用ExecutorService來實際運行作業。我想要工作線程(爲了爭論起見,我們稱他們爲JobManager-s)來通知鎖存器,即使它們拋出異常。一個JobManager可能需要一秒鐘和一小時之間的任何時間來完成,並可能在任何時候失敗。如果拋出異常,這個想法是調用JobManager的「終結器」方法。現在,ExecutorService喜歡捕捉異常,或者隱藏它沒有的真正起源。我雖然圍繞這幾個方面,這兩者都不是令人滿意的:Java的「定格」在異常

  1. 使用ExecutorService#execute(Runnable r)而非submit(Runnable r)。我可以這樣做,因爲我不在意JobManager的返回值。我提供了一個自定義的ThreadFactory,其中附加一個UncaughtExceptionHandler給每個新創建的線程。這種方法的問題是,當被調用UncaughtExceptionHandler#uncaughtException(Thread t, Throwable e)tRunnableThreadPoolExecutor$Worker是類型,並且不JobManager類型,它阻止我調用‘終結’方法的。

  2. 使用自定義ExecutorService並重寫afterExecute(Runnable r, Throwable t)方法。這遭受與1相同的問題。

  3. 將整個JobManager#doWork()包裝在catch語句中,並使用返回值指示是否拋出異常。我可以再submit的作業,然後使用FutureTask#get()決定是否引發異常。我不喜歡這個解決方案,因爲當你有詳盡的異常機制時,我覺得返回代碼是錯誤的工具。此外,get()將等待(除非中斷),這意味着我無法立即處理其他線程中的錯誤。

  4. 擺脫CountDownLatch的。將所有Future s存儲在列表中,並反覆插入,直到我滿意州爲止。這可能工作,但感覺像一個骯髒的黑客。

任何建議,非常感謝。

+0

我知道這是不是非常有幫助的,但是...... +1真的好格式。 –

+0

這個想法實際上並不是'如果拋出異常,就調用JobManager的'finalizer'方法'。這只是一個可能的實現。這個想法並不是實際上有最終確定方法。我強烈建議你重寫你的標題來表達你的實際問題。 – EJP

回答

4

據我瞭解,你可以使用一個簡單try - finally塊:

public class JobManager { 
    public void doWork() { 
     try { 
      ... 
     } finally { 
      countDownLatch.countDown(); 
     } 
    } 
}