Java:为线程池中的线程设置超时
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14236654/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: Set timeout for threads in a ThreadPool
提问by sk2212
I want to set timeouts for threads which are executed within a thread pool. At the moment I have following code:
我想为在线程池中执行的线程设置超时。目前我有以下代码:
ExecutorService executor = Executors.newFixedThreadPool(8);
for(List<String> l: partition) {
Runnable worker = new WorkerThread(l);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
The code just splits a big list of objects into sublists and process these sublist within single threads. But this is not the point.
该代码只是将一个大的对象列表拆分为子列表,并在单个线程中处理这些子列表。但这不是重点。
I want to give each single thread in the thread pool a timeout. For only one thread in the pool I found following solution:
我想给线程池中的每个线程一个超时。对于池中只有一个线程,我找到了以下解决方案:
Future<?> future = null;
for (List<String> l : partition) {
Runnable worker = new WorkerThread(l);
future = executor.submit(worker);
}
try {
System.out.println("Started..");
System.out.println(future.get(3, TimeUnit.SECONDS));
System.out.println("Finished!");
} catch (TimeoutException e) {
System.out.println("Terminated!");
}
But this would not work for more than one thread. Maybe I have to put each thread in a List<Future>
list and iterate over this list and set a timeout for each future
object?
但这不适用于多个线程。也许我必须将每个线程放在一个List<Future>
列表中并遍历该列表并为每个future
对象设置超时?
Any suggestions?
有什么建议?
EDIT AFTER USING CountDownLatch:
使用 CountDownLatch 后编辑:
CountDownLatch doneSignal = new CountDownLatch(partition.size());
List<Future<?>> tasks = new ArrayList<Future<?>>();
ExecutorService executor = Executors.newFixedThreadPool(8);
for (List<String> l : partition) {
Runnable worker = new WorkerThread(l);
tasks.add(executor.submit(doneSignal, worker));
}
doneSignal.await(1, TimeUnit.SECONDS);
if (doneSignal.getCount() > 0) {
for (Future<?> fut : tasks) {
if (!fut.isDone()) {
System.out.println("Task " + fut + " has not finshed!");
//fut.cancel(true) Maybe we can interrupt a thread this way?!
}
}
}
Works good so far.
到目前为止效果很好。
So next question is how to interrupt a thread which is timed out? I try fut.cancel(true)
and add following construct in some critical loops in the worker thread:
那么下一个问题是如何中断一个超时的线程?我尝试fut.cancel(true)
在工作线程的一些关键循环中添加以下构造:
if(Thread.interrupted()) {
System.out.println("!!Thread -> " + Thread.currentThread().getName() + " INTERRUPTED!!");
return;
}
So the worker thread is "killed" after the timeout. Is this a good solution?
所以工作线程在超时后被“杀死”。这是一个很好的解决方案吗?
Furthermore: Is it possible to get the name of the thread which timed out over the Future
interface? At the moment I have to print out the name in the if condition of the Thread.interrupted()
construct.
此外:是否可以获取通过Future
接口超时的线程的名称?目前我必须在Thread.interrupted()
构造的 if 条件中打印出名称。
Thanks for help!
感谢帮助!
Regards
问候
采纳答案by Fildor
Have you seen this? ExecutorService.invokeAll
你见过这个吗?ExecutorService.invokeAll
It should be exactly what you want: Invoke a bundle of workers and have them timeout if taking too long.
它应该正是您想要的:调用一组工作人员,如果花费太长时间,让他们超时。
EDIT after comment - (new idea):
You can use a CountDownLatchto wait for the tasks to finish AND timeout via await(long timeout, TimeUnit unit)
!
You can then even do a shutdownNow and see which tasks have taken too long ...
评论后编辑 -(新想法):您可以使用CountDownLatch等待任务完成并通过await(long timeout, TimeUnit unit)
! 然后您甚至可以执行 shutdownNow 并查看哪些任务花费了太长时间......
EDIT 2:
编辑2:
To make it clearer:
为了更清楚:
- Have a CountDownLatch be count down by each Worker, when finished.
- In the main execution thread
await
with timeout on said latch. - When that call returns, you can check the Latches's count to see if there has been the timeout hit (if it is >0).
- a) count = 0, all tasks finished in time.
b) if not, loop the Futures and check their
isDone
. You don't have to call shutdown on the ExecutorService. - Call shutdown if you do not need the Executor any longer.
- 完成后,让每个 Worker 对 CountDownLatch 进行倒计时。
- 在主执行线程中
await
,所述闩锁超时。 - 当该调用返回时,您可以检查锁存器的计数以查看是否存在超时命中(如果大于 0)。
- a) count = 0,所有任务按时完成。b) 如果没有,循环 Futures 并检查它们的
isDone
. 您不必在 ExecutorService 上调用 shutdown。 - 如果您不再需要 Executor,请调用 shutdown。
Note: Workers can finish in the meantime between the timeout and calling their Future's isDone().
注意:Worker 可以在超时和调用其 Future 的 isDone() 之间的这段时间内完成。