簡體   English   中英

Java SwingWorker取消合作嗎?

[英]Is Java SwingWorker cancellation cooperative?

希望能對您有所幫助。 我的理解是,取消SwingWorker線程是協作的。 但是,那不是我所看到的。

我下面的代碼將停止SwingWorker線程,即使我沒有可中斷的操作。 我不希望它能這樣工作。 對於測試請注意,我專門在doStuff()中放置了一個無限循環。 當我在main()例程中執行取消操作時:

worker.cancel(真),

我結束於done()函數,指示doInBackground()已退出(特別是在Exception處理程序中)。 看起來即使沒有可中斷的操作,該線程也被殺死了。 注意,如果我更改為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);

    }
}

我應該補充一點,我可以通過協作使我取消或通過輪詢isCancelled()中斷的睡眠來完全按照Java文檔中的描述進行這項工作。 只是想知道為什么要這樣做,就像上面的代碼片段一樣。 如果要冒一個危險,就好像我在調用worker.cancel()時,沒有描述剛剛描述的協作機制,然后就立即調用了done()函數。

SwingWorker.done()方法的文檔似乎有點錯誤。 它說done()被稱為“在doInBackground方法完成之后”。 但是,首先,即使您從未啟動SwingWorker,也顯然在取消SwingWorker時調用了done()。 其次,如果取消了SwingWorker,則即使doInBackground()方法尚未返回,也會立即調用done()。 這就是這里發生的事情。

調用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取消協作的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM