我想为线程池中执行的线程设置超时。目前,我有以下代码:
ExecutorService executor = Executors.newFixedThreadPool(8);
for(List<String> l: partition) {
Runnable worker = new WorkerThread(l);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
代码只是将一大堆对象拆分成子列表,并在单个线程中处理这些子列表。但这不是重点。
我想给线程池中的每个线程一个超时。对于池中只有一个线程,我找到了以下解决方案:
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!");
}
但这不适用于多个线程。也许我必须将每个线程放在一个List<Future>
列表中,然后遍历这个列表,并为每个future
对象设置一个超时。
有什么建议吗?
使用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?!
}
}
}
到目前为止效果还不错。
那么下一个问题是如何中断超时的线程?我尝试了fut.cancel(true)
,并在worker线程的一些关键循环中添加了以下结构:
if(Thread.interrupted()) {
System.out.println("-> " + Thread.currentThread().getName() + " INTERRUPTED");
return;
}
所以工作线程在超时后被“杀死”。这是一个好的解决方案吗?
此外:是否可以获得通过Future
接口超时的线程的名称?目前,我必须打印出Thread.interrupted()
构造的if条件中的名称。
感谢您的帮助!
问候
发布于 2013-01-09 22:06:56
你看过这个吗?ExecutorService.invokeAll
这应该正是您想要的:调用一组工作程序,如果花费的时间太长,让它们超时。
注释后编辑-(新想法):您可以通过await(long timeout, TimeUnit unit)
使用CountDownLatch来等待任务完成和超时!然后,您甚至可以执行shutdownNow,并查看哪些任务花费的时间太长……
编辑2:
更清楚地说:
当调用返回时,你可以检查锁存器计数,看看是否有超时命中(如果>0)。
=0,所有任务都及时完成。b)如果不是,循环期货并检查它们的isDone
。如果不再需要Executor,则不必在ExecutorService.
注意:工作者可以在超时和调用他们的未来的isDone()之间完成。
https://stackoverflow.com/questions/14236654
复制相似问题