InvokeAll超时中断

InvokeAll timeout interrupt

问题:

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

背景:

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

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

所以一秒钟后它就会超时,我可以继续我的一天。但是在后台,线程仍然处于活动状态并可能执行一些代码。基本上它们不会被中断,我不想发生这种情况 - 我希望线程停止执行。

invokeAll 达到超时后,是否有任何方法可以使用返回的 futures 列表来停止线程?

你不能两种方式。

ExecutorService "framework" 允许您只考虑 Callable 个对象和 Future 个结果。这种抽象隐藏了所涉及线程的所有底层细节。因此:即使有可能,您的想法也很可能是 "dirty hack".

换句话说:如果您想要低级、直接访问执行某些操作的线程 - 那么您可能必须使用自己的 "thread pooling" 实现。

中间立场:请记住,这些线程执行您的 Callable/Runnable 个实例。你当然可以想出一些东西,让那些对象 定期 检查某种 "command queue"。当队列包含 取消请求 - 然后 你的 Callable 中的代码停止工作。

ExecutorService 旨在支持 cancellation of tasks that respond to interruption. 因此,执行此操作的正确方法是让您的 Callable 实现注意到它们已被中断。

如果你的任务是纯计算性的,或者如果它经常循环,调用第三方库,这很容易。在您的任务中的某处,您将有一个类似于以下内容的循环:

while (!Thread.interrupted()) {
  /* Keep going */
}

当然,您也可以在循环中测试其他特定于任务的条件,但您应该测试当前线程的中断状态。

调用interrupted() will clear the interrupted status. Calling Thread.currentThread().isInterrupted()将保留中断状态。对于 ExecutorService 中的工作线程,保持中断状态并不重要——服务正在中断它自己的线程,当它的线程 returns 从你的任务中退出时,服务会清除状态而不看在它。但是,采用它是一个好习惯,因此如果将其合并到任务中,您的代码将运行良好。要在捕捉到 InterruptedException 或使用 Thread.interrupted() 检测到它后重新断言中断状态,只需调用 Thread.currentThread().interrupt().

如果任务是对不支持中断的第三方库的长时间 运行 调用,或者是对不间断 I/O 操作的阻塞调用,您的 "task" 就难多了。您可能完全不走运,或者您可能会找到一个杂牌来异步中止操作。

例如,如果您创建一个 Socket,并将它(或其流)传递给您的任务,您可以异步关闭套接字。如果 invokeAll 超时,调用者将需要额外的代码来关闭套接字。