你如何命名SwingWorker线程?开放代码或最佳实践

时间:2009-12-21 16:09:01

标签: java swing multithreading swingworker

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

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

4 个答案:

答案 0 :(得分:9)

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

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

答案 1 :(得分: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();

答案 2 :(得分:0)

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

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

答案 3 :(得分: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包中的一个类,所以你已经被警告了。