好的,所以解释这种情况有点复杂。它实际上并不像看起来那样危险。
我正在编写一个并发包,它完成两件事,它曾经在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上需要的关键假设,或者建议一个长期的解决方案 - 所有人都非常感激。谢谢!
答案 0 :(得分:1)
问题的第一部分是否与更好地使用Future
有关?
...在取消任务时立即调用done(),而任务可能仍在调用call()方法中。
您是否已使用Thread.interrupted()
方法手动核对call()
?
我们知道FutureTask.cancel()
的源代码,它只调用Thread.interrupt()
,这意味着只有一个代表线程中断状态的布尔标志才会被设置为true。除非调用InterruptedException
,Thread.sleep()
或.wait()
,否则不会抛出.join()
,因为后者3会检查标记并做出回复。
A sample is here,请阅读接受的答案。
此外,取消使得无法检索部分结果。
是。您可以将部分结果泄漏到任务外的Hashmap
。或者直截了当地将结果作为外部的最终变量初始化,然后在内部使用它(call()
& done()
)。实际上我之前已经将百分比字段保存到KV商店中。