首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java:为ThreadPool中的线程设置超时

Java:为ThreadPool中的线程设置超时
EN

Stack Overflow用户
提问于 2013-01-09 21:47:45
回答 1查看 19.3K关注 0票数 9

我想为线程池中执行的线程设置超时。目前,我有以下代码:

代码语言:javascript
运行
复制
ExecutorService executor = Executors.newFixedThreadPool(8);
for(List<String> l: partition) {            
    Runnable worker = new WorkerThread(l);
    executor.execute(worker);
}       

executor.shutdown();
while (!executor.isTerminated()) {

}

代码只是将一大堆对象拆分成子列表,并在单个线程中处理这些子列表。但这不是重点。

我想给线程池中的每个线程一个超时。对于池中只有一个线程,我找到了以下解决方案:

代码语言:javascript
运行
复制
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后编辑:

代码语言:javascript
运行
复制
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线程的一些关键循环中添加了以下结构:

代码语言:javascript
运行
复制
if(Thread.interrupted()) {
    System.out.println("-> " + Thread.currentThread().getName() + " INTERRUPTED");
        return;
}

所以工作线程在超时后被“杀死”。这是一个好的解决方案吗?

此外:是否可以获得通过Future接口超时的线程的名称?目前,我必须打印出Thread.interrupted()构造的if条件中的名称。

感谢您的帮助!

问候

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-01-09 22:06:56

你看过这个吗?ExecutorService.invokeAll

这应该正是您想要的:调用一组工作程序,如果花费的时间太长,让它们超时。

注释后编辑-(新想法):您可以通过await(long timeout, TimeUnit unit)使用CountDownLatch来等待任务完成和超时!然后,您甚至可以执行shutdownNow,并查看哪些任务花费的时间太长……

编辑2:

更清楚地说:

当调用返回时,你可以检查锁存器计数,看看是否有超时命中(如果>0)。

  1. a) CountDownLatch = 0,
  2. =0,所有的任务都及时完成。
  3. a)

=0,所有任务都及时完成。b)如果不是,循环期货并检查它们的isDone。如果不再需要Executor,则不必在ExecutorService.

  1. Call关闭时调用shutdown。

注意:工作者可以在超时和调用他们的未来的isDone()之间完成。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14236654

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档