好吧,解释这种情况有点复杂。它实际上并不像看起来那么有风险。
我正在编写一个并发包,它可以做两件事,它曾经在 JDK 6 上完美工作。它做的第一件事是提供一个更好的 Future
接口(interface),允许使用事件监听器在任务完成时进行回调。 “但是你可以使用 FutureTask
的 done()
来实现!”你可能会说。问题在于,当任务被取消时,done()
会立即被调用,而任务可能仍在其 call()
方法中执行操作。此外,取消会导致无法检索部分结果。因此,我自己的包通过扩展现有包(包括新的线程池,但大部分实现都在那里重用)来修复这些问题。
该包所做的第二件事是解决常见的 GUI 问题。假设用户单击“保存”来保存图像。如果图像很大,最好显示进度监视器而不是卡住界面。但如果文档很小,进度监视器的突然闪烁会让用户感到困惑。而且我们不能设定最短弹出时间 - 这会减慢工作流程。我的解决方案在这两者之间进行折衷。其效果是 EDT “卡住”任务完成所需的时间,或者,如果需要的时间超过 1 秒,则显示具有最短弹出时间的进度监视器。效果还是比较优雅的。这在 JDK6 中也能完美运行,甚至可以与多个线程一起运行。
问题:在 JDK7 中,上面的卡住部分现在出现了一个微妙的错误。我的代码的一个关键假设是传递给 由于实现错误,没关系。SwingUtilities.invokeLater()
的 Runnable
将不会与其他事件分派(dispatch)线程内容同时运行。因此,当 Runnable 运行时,EDT 无法处理按钮点击、加速器、其他事件等。 (这被用来在卡住期间停止所有输入)但这似乎在 JDK7 中发生了变化。在我的调试中,我注意到 Runnable
可能正在运行,而按钮按下代码仍在运行!由于后面的事情,这很快就会导致死锁。
像这样滥用 EDT 是有风险的,但在当时这是唯一有效的方法。一些人建议使用 GlassPane
来拦截事件。但它无法拦截加速器。我当时尝试的其他一切也都受到这种方式的限制。
我现在的问题是是否有人能找到更好的方法来做到这一点。如果您认为我的Future
问题可以以更好的方式解决,请告诉我们。最重要的是,如果您能找到解决上述 GUI 问题的方法,或者停止输入,或者保证我在 JDK 上需要的关键假设,或者提出一个长期解决方案 - 所有人都非常感激。谢谢!
最佳答案
问题的第一部分是否与更好地使用 Future
有关?
... done() is called immediately when a task is cancelled, while the task might still be doing stuff in its call() method.
您是否在 call()
方法中手动检查了 Thread.interrupted()
?
从FutureTask.cancel()
的源码中我们知道,它只是调用了Thread.interrupt()
,这意味着只有一个代表线程中断状态的 boolean 标志会被设置为true。除非调用 Thread.sleep()
、.wait()
或 .join()
,否则不会抛出 InterruptedException
,因为后 3 个它们会检查标志并做出响应。
A sample is here ,请阅读已接受的答案。
Also, cancelling makes it impossible to retrieve partial results.
是的。您可能会将部分结果泄漏到任务外部的Hashmap
。或者直接,将结果初始化为外部的最终变量,然后在内部使用它(call()
& done()
)。其实我以前曾经将百分比字段保存到KV存储中。
关于java - 暂时停止事件调度线程 Activity (v7),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20552211/