2012-08-02 57 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