问题:
如何使invokeAll
停止执行超时的一系列线程。
背景:
我有一个callables
的列表,我想等待完成。但是,如果他们不能在规定的时间内完成(比如一秒钟),我想取消它们。
executor.invokeAll(callables, 1000l, TimeUnit.MILLISECONDS);
所以过了一会儿就会很快就结束了,我可以继续我的一天。但是在后台,线程仍处于活动状态,可能会执行一些代码。基本上它们没有被打断,我不想发生 - 我希望线程停止执行。
有没有办法在invokeAll
达到超时后使用返回的期货清单停止线程?
答案 0 :(得分:1)
你不能两种方式。
ExecutorService"框架"允许您仅考虑Callable
个对象和Future
结果。这种抽象隐藏了所涉及的线程的所有低级细节。因此:即使有可能,你的想法很可能是一个肮脏的黑客"。
换句话说:如果你想要低级,直接访问线程做某事 - 那么你可能必须使用你自己的"线程池"实现。
中间地带:请记住,这些线程会执行您的 Callable / Runnable实例。你当然可以想一想这些对象经常检查某种"命令队列"。当队列包含取消请求时 - 然后你的代码在Callable停止工作。
答案 1 :(得分:1)
ExecutorService
旨在支持cancellation响应interruption.的任务。因此,正确的方法是让您的Callable
实施通知他们已经被打断了。
如果你的任务纯粹是计算的,或者它经常循环,调用第三方库,这很容易。在你的任务的某个地方,你将有一个看起来像这样的循环:
while (!Thread.interrupted()) {
/* Keep going */
}
当然,您也可以在循环中测试其他特定于任务的条件,但是您应该测试当前线程的中断状态。
调用interrupted()
将清除中断状态。调用Thread.currentThread().isInterrupted()
将保留中断状态。对于ExecutorService
中的工作线程,保持中断状态并不重要 - 服务正在中断其自己的线程,并且当其线程从您的任务返回时,该服务将清除状态而不查看它。但是,采用这是一个好习惯,这样如果将代码合并到任务中,代码就能很好地运行。要在抓取InterruptedException
或使用Thread.interrupted()
检测到中断状态后重新确认中断状态,只需致电Thread.currentThread().interrupt()
。
如果任务是长时间调用不支持中断的第三方库,或者阻止调用不间断I / O操作,则“任务”要困难得多。你可能完全没有运气,或者你可能找到一个kludge来异步中止操作。
例如,如果您创建Socket
并将其(或其流)传递给您的任务,则可以异步关闭套接字。如果invokeAll
超时,调用者将需要额外的代码来关闭套接字。