【问题标题】:How do you name a SwingWorker thread? Open to code or best practices如何命名 SwingWorker 线程?开放代码或最佳实践
【发布时间】:2009-12-21 16:09:01
【问题描述】:

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

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

【问题讨论】:

    标签: java swing multithreading swingworker


    【解决方案1】:

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

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

    【讨论】:

    • 不错的答案。简单直接。
    【解决方案2】:

    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();
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        最佳实践是使用已经提到的 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 包中的一个类,所以你已经被警告过了。

        【讨论】:

        • sun 包和“最佳实践”本身就是矛盾的 :-)
        • “最佳实践”是使用 Thread.setName(String)。使用 sun 包是一个“技巧”。
        【解决方案5】:

        导入 javax.swing.SwingWorker;

        public class SwingWorkerName {
        
            public static void main(String[] args) throws Exception {
                new SwingWorker() {
                    @Override
                    protected Object doInBackground() throws Exception {
                        final String previousThreadName = Thread.currentThread().getName();
                        Thread.currentThread().setName("My Worker Thread");
                        try {
        
                            // DO YOUR WORK HERE
                            Thread.sleep(100000L);
        
                            return null; // or return whatever you want
                        } finally {
                            Thread.currentThread().setName(previousThreadName);
                        }
                    }
                }.execute();        
                Thread.sleep(100000L);
            }
        
        }
        

        注意:在 NetBeans 中,swingworker 线程的新名称直到我暂停应用程序或遇到断点后才会出现在调试器中。

        【讨论】:

          猜你喜欢
          • 2014-06-14
          • 1970-01-01
          • 2010-10-14
          • 2011-08-09
          • 1970-01-01
          • 2015-05-28
          • 1970-01-01
          • 2022-11-10
          • 2022-01-19
          相关资源
          最近更新 更多