[英]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.