有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程是Java SwingWorker协作的吗?

如果您能帮助我理解这一点,我将不胜感激。我的理解是取消SwingWorker线程是合作的。然而,这不是我所看到的

下面的代码将停止SwingWorker线程,即使我没有可中断的操作。我没想到会这样。请注意,在测试中,我专门在doStuff()中放置了一个无限循环。在main()例程中执行取消操作时:

工人。取消(真)

我在done()函数中结束,指示doInBackground()已退出(特别是在异常处理程序中)。看起来,即使在没有可中断操作的情况下,线程也会被终止。请注意,如果我更改为worker。取消(false),我得到同样的效果

class AWorker extends SwingWorker<String, Object> {
    void doStuff() {
        System.out.println("Entered doStuff");    
        while (true);
    }

    @Override
    public String doInBackground() {
        //System.out.println("doInBackground started");
        doStuff();
        return "hello";
    }

    @Override
    protected void done() {
        try {
            System.out.println("done() entered");
            String status = get();
            System.out.println("done(): get = " + status);
        } catch (Exception e) {
            System.out.println("done(): Exception: " + e);
        }
    }

    public static void main(String[] args) throws Exception {
        AWorker worker = new AWorker();
        worker.execute();

        Thread.sleep(5000);
        worker.cancel(true);

    }
}

我应该补充一点,我可以完全按照Java文档中所描述的那样,通过协作进入一个在我取消时被中断的睡眠状态,或者通过轮询isCancelled()来完成这项工作。我只是想知道为什么它会像我上面的代码片段中那样。如果我冒昧地猜一猜的话,我给工人打电话的时候看起来是这样的。cancel()不使用刚才描述的协作机制,则立即调用done()函数


共 (1) 个答案

  1. # 1 楼答案

    SwingWorker.done()方法的文档似乎有点错误。它说done()是“在doInBackground方法完成后”调用的。但是,首先,当你取消SwingWorker时,done()显然也会被调用,即使你从未启动过它。其次,如果取消SwingWorker,则会立即调用done(),即使doInBackground()方法尚未返回。这就是这里发生的事情

    调用done()时,无限循环仍在运行。我确认使用以下代码将所有线程堆栈跟踪转储到控制台:

    static void dumpThreads() {
        for (java.util.Map.Entry<Thread,StackTraceElement[]> t : Thread.getAllStackTraces().entrySet()) {
            System.out.println(t.getKey() + ":");
            for (StackTraceElement e : t.getValue()) {
                System.out.println("    " + e);
            }
        }
    }
    

    我在done()中插入了对该方法的调用。其中一个线程堆栈跟踪显示无限循环在当时仍然有效:

    Thread[SwingWorker-pool-1-thread-1,5,main]:
        AWorker.doStuff(AWorker.java:8)
        AWorker.doInBackground(AWorker.java:14)
        javax.swing.SwingWorker$1.call(SwingWorker.java:295)
        java.util.concurrent.FutureTask.run(FutureTask.java:266)
        javax.swing.SwingWorker.run(SwingWorker.java:334)
        java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        java.lang.Thread.run(Thread.java:744)
    

    然而,无限循环确实会在不久之后被强制停止,不是由SwingWorker停止,而是在程序结束时停止,因为当没有非守护进程线程运行(SwingWorker线程是守护进程线程)并且没有创建窗口时,程序会退出。这两件事(不可靠的文档和自动退出)的结合让人觉得取消SwingWorker可以神奇地停止任务,但事实并非如此

    如果从主方法打开一个窗口,将阻止程序自动退出。然后,您将从系统任务管理器中看到,该程序一直在运行(并在无限循环中占用CPU),直到您终止它

    简而言之,是的,SwingWorker取消是合作的