2017-09-13 94 views
1

问题invokeAll是超时中断

如何做出一系列已经与invokeAll停止执行超时线程。

背景

我有callables我想等完成的列表。但是,如果他们没有在规定时间内完成(比如说一秒),我想取消它们。这似乎很容易与

executor.invokeAll(callables, 1000l, TimeUnit.MILLISECONDS); 

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

有没有什么方法可以在invokeAll超时后使用返回的期货清单来停止线程?

+0

该文档说,返回的任务未完成时将被取消。 http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html#invokeAll%28java.util.Collection,%20long,%20java.util.concurrent.TimeUnit%29 – pshirishreddy

+0

我认为他们被取消了,但他们仍然活着,甚至在'invokeAll'已经停止阻止后可以继续记录。 – Deepak

+0

线程在做什么?有线程没有响应中断的各种可能的原因(阻塞IO,代码吃掉中断,代码忽略中断,等待进入同步块...) – bowmore

回答

1

你不能有方式。

ExecutorService“框架”允许您仅考虑Callable对象和Future结果。这个抽象隐藏了涉及的所有线程的低级细节。因此:即使这是可能的,你的想法很可能是一个“肮脏的黑客”。换句话说:如果你想低级别的,直接访问线程做某事 - 那么你可能必须使用自己的“线程池”实现。

中间层:请记住这些线程执行您的 Callable/Runnable实例。你当然可以想到这些对象定期检查某种“命令队列”。当队列包含取消请求 - 然后您的 Callable中的代码停止执行其工作。

+0

你的评论是有道理的,但我真的不会避风港当我给'invokeAll'超时时,我认为这将是标准行为。很奇怪的是,保持运行的线程是“有效停止”的,但在调用引发'InterruptedException'的事件之前不会中断。对于被中断的异常,应该有更高级别的轮询方式 – Deepak

+0

问题是:“中断”线程并不是你在Java中“常用”的做法。当你长时间运行Runnable/Callable代码时,那么你有该代码以某种方式检查一些“取消”标志。 – GhostCat

1

ExecutorService被设计为支持,以应对interruption.任务cancellation因此,要做到这一点,正确的方法是使你的Callable实现注意到他们已经中断。

如果您的任务纯粹是计算上的,或者它经常循环,调用第三方库,这很容易。某处在你的任务,你将有一个循环,看起来像:

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

当然,你可能在你的循环测试等特定任务的条件太多,但你应该是测试电流的断续状态线。

调用interrupted()将清除中断状态。调用Thread.currentThread().isInterrupted()将保持中断状态。对于ExecutorService中的工作线程,保持中断状态无关紧要—服务正在中断它自己的线程,并且当线程从您的任务返回时,服务将清除状态而不查看它。但是,这是一个很好的习惯,所以如果你的代码被合并到一个任务中,它将会很好地工作。在获取InterruptedException或使用Thread.interrupted()检测后重新断言中断状态,只需致电Thread.currentThread().interrupt()即可。

如果任务是对不支持中断的第三方库的长期调用,或者阻止对不间断I/O操作的调用,那么您的“任务”要困难得多。你可能完全没有运气,或者你可能会发现一个混乱异步中止操作。

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

相关问题