【问题标题】:Java thread trobleshooting for SwingWorker like tasksSwingWorker 之类任务的 Java 线程故障排除
【发布时间】:2012-08-02 00:09:37
【问题描述】:

线程转储包含大量信息。例如,如果我怀疑某个动作触发了多次,那么我需要做的就是在每次触发该动作时转储堆栈跟踪,然后调查堆栈是否有错误的动作触发。

在某些情况下,鼓励开发人员放弃顺序执行的概念简单性。例如,Swing 提供 SwingWorker 帮助程序来解决单线程 EDT 的限制。现在,如果我转储堆栈跟踪,它就没有用了,因为该操作是由 SwingWorker 触发的,并且没有关于谁启动了 SwingWorker 任务的信息。

那么,我该如何排除故障?是否有“重定向”线程转储以遵循真正原因的巧妙技巧?

【问题讨论】:

    标签: java multithreading swing swingworker


    【解决方案1】:

    您可以扩展 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)
    

    【讨论】:

      【解决方案2】:

      我可能会告诉你一些你已经知道的事情,但我建议 ThreadDump

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

      如果你使用 IDE,那么这很好:

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

      为此我经常使用 Eclipse。调试器视图具有可视化和跟踪多个线程、打印堆栈和暂停它们的方法。

      【讨论】:

      • 启动 SwingWorker 作业的线程进一步推进,因此目前在工作人员作业中发生有趣事件,触发它的信息在线程转储/调试器状态中丢失。
      • 我明白了。你知道什么触发和捕获事件。如果这样做,您可以使用 DynamicProxy 装饰该方法以暂停或打印堆栈跟踪。
      猜你喜欢
      • 2023-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-15
      相关资源
      最近更新 更多