暂时停止事件调度线程活动(v7)

时间:2013-12-12 19:14:25

标签: java multithreading swing user-interface

好的,所以解释这种情况有点复杂。它实际上并不像看起来那样危险。

我正在编写一个并发包,它完成两件事,它曾经在JDK 6上完美地工作。它首先做的是提供一个更好的Future接口,它允许在任务完成时使用事件进行回调听众。 “但你可以使用FutureTask的{​​{1}}!”你可能会说。问题是当任务被取消时会立即调用done(),而任务可能仍然在其done()方法中执行操作。此外,取消使得无法检索部分结果。所以我自己的软件包通过扩展现有的软件包(包括一个新的线程池,但大部分实现在那里重用)来解决这些问题。

Part of my progress monitor solution http://i44.tinypic.com/16bexzb.jpg

该软件包的第二件事是解决一个常见的GUI问题。假设用户单击“保存”以保存图像。如果图像很大,那么显示进度监视器而不是冻结界面会很好。但是如果文档很小,那么进度监视器的突然闪烁会使用户感到困惑。而且我们不能有最短的弹出时间 - 这会减慢工作流程。我的解决方案在这两者之间妥协。结果是EDT在任务完成时“冻结”,或者如果花费的时间超过1秒,则显示具有最小弹出时间的进度监视器。效果相当优雅。这也在JDK6中完美运行,甚至可以与多个线程协同工作。

问题:在JDK7中,上面的冻结部分现在有一个微妙的错误。对我的代码的一个重要假设是传递给call()的{​​{1}}将与其他事件派发线程内容同时运行。因此,当Runnable运行时,EDT无法处理按钮点击,加速器,其他事件等。 (这被用来在冻结期间停止所有输入)但是这似乎在JDK7中已经改变了。在我的调试中,我注意到按下代码的按钮仍在运行时SwingUtilities.invokeLater()可能正在运行!这会很快导致由于后来的东西造成的死锁。由于实施错误,没关系。

像这样滥用EDT是有风险的,但在当天它是唯一有用的东西。有人建议使用Runnable拦截事件。但它不能拦截加速器。我当时尝试的其他所有东西也都以这种方式受到限制。

现在我的问题是,如果有人看到更好的方法来做到这一点。如果您认为我的Runnable问题可以更好地解决,请告诉我们。最重要的是,如果您能够找到解决上述GUI问题的方法,或者停止输入,或者保证我在JDK上需要的关键假设,或者建议一个长期的解决方案 - 所有人都非常感激。谢谢!

1 个答案:

答案 0 :(得分:1)

问题的第一部分是否与更好地使用Future有关?

  

...在取消任务时立即调用done(),而任务可能仍在调用call()方法中。

您是否已使用Thread.interrupted()方法手动核对call()

我们知道FutureTask.cancel()的源代码,它只调用Thread.interrupt(),这意味着只有一个代表线程中断状态的布尔标志才会被设置为true。除非调用InterruptedExceptionThread.sleep().wait(),否则不会抛出.join(),因为后者3会检查标记并做出回复。

A sample is here,请阅读接受的答案。

  

此外,取消使得无法检索部分结果。

是。您可以将部分结果泄漏到任务外的Hashmap。或者直截了当地将结果作为外部的最终变量初始化,然后在内部使用它(call()& done())。实际上我之前已经将百分比字段保存到KV商店中。