InvokeAll超时中断

时间:2017-09-13 13:58:46

标签: java multithreading executorservice

问题

如何使invokeAll停止执行超时的一系列线程。

背景

我有一个callables的列表,我想等待完成。但是,如果他们不能在规定的时间内完成(比如一秒钟),我想取消它们。

这似乎很容易
executor.invokeAll(callables, 1000l, TimeUnit.MILLISECONDS);

所以过了一会儿就会很快就结束了,我可以继续我的一天。但是在后台,线程仍处于活动状态,可能会执行一些代码。基本上它们没有被打断,我不想发生 - 我希望线程停止执行。

有没有办法在invokeAll达到超时后使用返回的期货清单停止线程?

2 个答案:

答案 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超时,调用者将需要额外的代码来关闭套接字。