3

我正在尝试调试 SwingWorker 线程中发生的可怕异常。如果我可以命名我的 SwingWorker 线程,那么我可以更好地解释我收到的堆栈跟踪。

似乎无法命名 SwingWorker 线程(是吗?)。我正在寻找任何最佳实践或“技巧”来帮助我正确识别我的工作线程,而不仅仅是在我的代码中添加日志语句。

4

4 回答 4

9

虽然您无权访问 SwingWorker 正在使用的 ThreadFactory,但您可以在 SwingWorker 正在运行的任何类的 run() 或 call() 方法中调用 Thread.currentThread().setName() 。

只需确保在线程实际执行代码时设置了该值

于 2009-12-21T16:24:56.310 回答
1

SwingWorker 使用的线程来自 Executors.defaultThreadFactory,这意味着它来自池。因此,如果“MyXYZThread”被系统中另一个未能重命名线程的 SwingWorker 重用,那么命名线程可能会产生误导。

我会扩展 SwingWorker 以包含一个名称并在引发异常时记录该名称。

注意:我宁愿不让调用者负责处理异常,但我没有看到不改变 SwingWorker 合同的方法。

private static abstract class MySwingWorker<X, Y> extends SwingWorker<X, Y>
{
    private final String taskName;
    public MySwingWorker(String name)
    {
        this.taskName = name;
    }
    public String getTaskName() {
        return taskName;
    }
}

用法:

new MySwingWorker<Object,Object>("my task") {
    protected Object doInBackground() {
        try {
            return someCall();
        }
        catch(Exception e) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, 
                "Exception in " + getTaskName(), e);
            throw e;
        }
    }
}.execute();
于 2009-12-21T16:44:54.587 回答
0

您应该能够使用反射来获取线程并调用 setName 。您需要使用 setAccessible 方法来执行此操作,并进行一些挖掘以找到您需要访问的变量的名称。

我不喜欢这种方法,但它可能和其他任何方式一样“hacky”......

于 2009-12-21T16:45:33.307 回答
0

最佳实践是使用已经提到的 Thread.currentThread().setName(String)。

一个“技巧”是为 SwingWorkers 设置 ThreadFactory:

sun.awt.AppContext context = sun.awt.AppContext.getAppContext();

int maxWorkers = 10;
ThreadFactory factory = ...
ExecutorService executor = Executors.newFixedThreadPool(maxWorkers, factory);

context.put(SwingWorker.class, executor);

这使用了 sun.awt 包中的一个类,所以你已经被警告过了。

于 2013-10-16T13:10:04.193 回答