java - Java SwingWorker取消是合作的吗?

标签 java multithreading swingworker

希望能帮助您理解这一点。我的理解是,SwingWorker 线程的取消是合作性的。然而,这不是我所看到的。

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

worker.cancel(true),

我最终进入了 did() 函数,表明 doInBackground() 已退出(特别是在异常处理程序中)。即使没有可中断的操作,线程也似乎被杀死了。请注意,如果我更改为worker.cancel(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);

    }
}

我应该补充一点,我可以通过合作地进入一个在我取消时被中断的 sleep 或通过轮询 isCancelled() 来使这项工作完全按照 Java 文档中的描述进行。只是想知道为什么它会像我上面的代码片段中那样做。如果我大胆猜测一下,看起来当我在没有刚才描述的协作机制的情况下调用worker.cancel()时,就会立即调用done()函数。

最佳答案

SwingWorker.done() 的文档方法好像有点不对。它说“doInBackground 方法完成后”调用done()。但是,首先,当您取消 SwingWorker 时,即使您从未启动过它,done() 显然也会被调用。其次,如果取消 SwingWorker,则立即调用 did(),即使 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 取消合作的。

关于java - Java SwingWorker取消是合作的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27309700/

相关文章:

java - Sikuli:Java 未找到错误

java - 如何在android中为Toast自定义背景、背景颜色和文字颜色

JavaFX 2.1 和线程? - 或 - 优雅地结束 JavaFX 应用程序?

java - 将 JasperReports 中的 NullPointerException 获取到多线程应用程序中

java - Swing/SwingWorker 初学者的问题

java - Akka 和 Ask 模式。当 Actor 突然停止时我可以返回 Future 吗?

java - 如何在java多线程环境中复制ArrayList<T>?

java - 我无法停止 java SwingWorker 进程

java - 如何等到 SwingWorker 完成?

java - IntelliJ IDEA 告诉我 "Error:java: Compilation failed: internal java compiler error idea"