2012-08-02 70 views
4

線程轉儲包含豐富的信息。例如,如果我懷疑某個動作不止一次被觸發,那麼我所需要做的就是在每次觸發動作時轉儲堆棧跟蹤,然後調查堆棧是否有錯誤的動作觸發。針對SwingWorker類似任務的Java線程故障排除

在某些情況下,鼓勵開發人員放棄順序執行的概念簡單性。例如,Swing提供SwingWorker助手來解決單線程EDT的侷限性。現在,如果我轉儲堆棧跟蹤,它是沒用的,因爲該操作是由SwingWorker觸發的,並且沒有關於誰啓動了SwingWorker任務的信息。

那麼,我該如何排除故障?是否有一個巧妙的把「重定向」線程轉儲跟蹤真正原因的技巧?

回答

2

您可以擴展SwingWorker以在創建時記錄堆棧(或執行時,但之後需要創建另一個執行方法,因爲它是最終的)。共創事業是相對昂貴,但這樣你可能會想這樣做,只有當調試(檢查日誌級別或類似)

import java.util.concurrent.ExecutionException; 
import javax.swing.SwingWorker; 

public abstract class TracedSwingWorker<T, V> extends SwingWorker<T, V> { 

    private final Exception cause; 

    public TracedSwingWorker() { 
     super(); 
     this.cause = new Exception("TracedSwingWorker created at:"); 
    } 

    @Override 
    protected final T doInBackground() throws Exception { 
     try { 
      return doWorkInBackground(); 
     } 
     catch(Exception e) { 
      if(this.cause != null) { 
       Throwable cause = e; 
       while(cause.getCause() != null) { 
        cause = cause.getCause(); 
       } 

       cause.initCause(this.cause); 
      } 

      throw e; 
     } 
    } 

    protected abstract T doWorkInBackground(); 

    // just for testing 
    public static void main(String[] args) { 
     new TracedSwingWorker<Void, Void>() { 
      @Override 
      protected Void doWorkInBackground() { 
       throw new IllegalArgumentException("Exception in TracedSwingWorker!"); 
      } 

      @Override 
      protected void done() { 
       try { 
        get(); 
       } 
       catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       catch (ExecutionException e) { 
        e.printStackTrace(); 
       } 
      } 
     }.execute(); 
    } 
} 

打印:

java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Exception in SwingWorker! 
     at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222) 
<snip> 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
     at java.lang.Thread.run(Thread.java:662) 
    Caused by: java.lang.Exception: SwingWorker created at: 
     at TracedSwingWorker.<init>(TracedSwingWorker.java:15) 
     at TracedSwingWorker$2.<init>(TracedSwingWorker.java:60) 
     at TracedSwingWorker.main(TracedSwingWorker.java:60) 
0

我可能會告訴你,你已經知道的東西,但我建議ThreadDump

http://www.oracle.com/technetwork/java/javase/tooldescr-136044.html#gbmpn

如果你使用IDE,那麼這是件好事:

的NetBeans http://netbeans.org/kb/docs/java/debug-multithreaded.html

我用Eclipse做了很多。調試器視圖具有可視化和跟蹤多個線程,打印堆棧和暫停它們的方法。

+0

其發起的SwingWorker工作的進展進一步的線程,因此目前在工作者作業中發生的一個有趣事件發生了,而在線程轉儲/調試器狀態中,丟失了這些信息。 – 2012-08-02 15:41:51

+0

我明白了。你知道火災發生的原因嗎?如果你這樣做,你可以使用DynamicProxy裝飾該方法來暫停或打印堆棧跟蹤。 – Edmon 2012-08-02 19:28:55