为java.util。concurrent.ExecutorService中的每个执行设置超时

时间:2012-01-06 12:19:43

标签: java timeout executorservice

如何使用java.​util.​concurrent.ExecutorService为每个并行运行的命令创建超时?

我的代码是这样的:
例如,在下面的代码中,我需要obj1运行最多1分钟,obj2运行2分钟,其他运行5分钟。

ExecutorService exService;
exService = Executors.newCachedThreadPool();
exService.execute(obj1);
exService.execute(obj2);
exService.execute(obj3);
exService.execute(obj4);
exService.shutdown();
boolean finshed = exService.awaitTermination(5, TimeUnit.MINUTES);
if (finshed) {
    //Doing something
}

修改
不幸的是,obj1 - obj4的类正在使用WebHarvest来抓取一些网页,这些网页使用jakarta HttpClient来读取网页和HttpClient(而且WebHarvest本身都没有)在整个页面读取时没有任何超时功能和/或刮擦工作 这是我耗时的任务,我想在超时后杀死ExecutorService线程来处理这个问题。

3 个答案:

答案 0 :(得分:3)

通常,没有可靠的方法来单独退出线程。特别是,在从该任务外部超时后,没有可靠的方法来中断和停止您的任务。你需要做的是让任务本身负责在他们的时间用完之后停止。根据它们的作用,您可以将此行为抽象为超类,如:

public abstract class TimeoutRunnable implements Runnable {
   private final long timeLimitMillis;
   private long startTimeMillis;

   public TimeoutRunnable(long timeLimitMillis) {
      this.timeLimitMillis = timeLimitMillis;
   }

   public final void run() {
      startTimeMillis = System.currentTimeMillis();
      while (System.currentTimeMillis() - startTimeMillis < timeLimitMillis) {
         runIteration();
      }
   }

   protected abstract void runIteration();
}

然后在子类覆盖中,runIteration()并执行任务的单个“步骤”。

答案 1 :(得分:1)

杀死任务的唯一合理可靠的方法是在单独的进程中运行它并在超时时终止该进程。使用任何其他方法与不支持超时的库可能最容易出错。

答案 2 :(得分:1)

从我的观点来看,我认为这些东西需要比普通Java标准类更强大的基础,这就是为什么我建议使用任何可能给你的调度程序基础结构(Quartz或任何其他项目)的原因处理(作业标识符)以消耗耗时的任务。

你可能有这样的事情:

Main Thread启动Quartz Scheduler,接收来自不同作业的订阅 说:Job1,Job 2和TimeCheckerJob

TimeCheckerJob将是一个永远的工作,通知任何新的工作,并将检查每个任何新工作的生活时间......在这项工作中,你将不得不处理每个工作的开始时间,小心OS时钟和不要试图设置太多的约束(纳秒是纯粹的虚构)。

HTH 我的2美分 杰罗姆