我正在尝试调试SwingWorker线程中发生的可怕异常。如果我可以命名我的SwingWorker线程,那么我可以更好地解释我收到的堆栈跟踪。
似乎无法命名SwingWorker线程(是吗?)。我正在寻找任何最佳实践或“技巧”,以帮助我正确识别我的工作线程,而不仅仅是使用日志语句来编写我的代码。
答案 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包中的一个类,所以你已经被警告了。