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
超时,调用者将需要额外的代码来关闭套接字。
问题:
如何让一系列超时的线程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
超时,调用者将需要额外的代码来关闭套接字。