2014-12-05 55 views
1

希望在理解这一点方面有所帮助。我的理解是取消SwingWorker线程是合作的。但是,这不是我所看到的。Java SwingWorker取消合作?

我下面的代码将停止SwingWorker线程,即使我没有可中断的操作。我不希望它以这种方式工作。对于测试我注意到在doStuff()中专门设置了一个无限循环。当我做了消除在main()函数:

worker.cancel(真),

我在做()函数最终表明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); 

    } 
} 

我要补充一点,我可以使这项工作完全一样时,我取消被中断睡眠或通过轮询isCancelled共同把()在Java文档中描述。只是想知道为什么它会在我上面的代码片段中做到这一点。如果我冒险猜测,看起来像当我调用worker.cancel()而没有刚描述的协作机制时,那么done()函数会立即被调用。

回答

0

SwingWorker.done()方法的文档似乎有点不对。它说done()被称为“doInBackground方法完成后”。但是,首先,即使您从未开始过,取消SwingWorker时,done()也显然会被调用。其次,如果你取消了SwingWorker,那么即使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); 
     } 
    } 
} 

我插入一个呼叫到该方法内完成()。其中一个线程的堆栈跟踪表明,无限循环仍然健在当时:

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取消合作。

+0

非常有启发性的分析表明doInBackground在SwingWorker被取消后仍然实际执行。 如果更新Java文档以更准确地反映发生的情况,那将会很棒。我试图提交错误报告,但Oracle提交错误报告的过程非常可怕。 – lucyimhome 2014-12-16 03:32:23