针对SwingWorker的Java线程故障排除任务

Teg*_*shi 5 java swing multithreading swingworker

线程转储包含大量信息.例如,如果我怀疑某个动作不止一次被触发,那么我需要做的就是每次触发动作时转储堆栈跟踪,然后调查堆栈以查找错误的动作.

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

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

Wal*_*aan 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

印刷:

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)
Run Code Online (Sandbox Code Playgroud)