【问题标题】:putting a timeout for each of executes in java.​util.​concurrent.ExecutorService在 java.​util.​concurrent.ExecutorService 中为每个执行设置超时
【发布时间】:2012-01-06 12:19:43
【问题描述】:

如何使用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 抓取一些网页,该 WebHarvest 使用 jakarta HttpClient 来读取网页,而 HttpClient(而且 WebHarvest 本身也没有)没有任何功能可以在整个页面读取和/或抓取时超时工作。
这是我的耗时任务,我想在超时后杀死 ExecutorService 线程来处理这个问题。

【问题讨论】:

  • 这应该回答你的问题:stackoverflow.com/questions/2758612/…
  • 该解决方案取决于Thread#interrupt()。根据任务正在做什么,这可能没有实际效果,因为中断机制仅适用于某些阻塞操作;它不是一般的Thread#stop 替代品。见docs.oracle.com/javase/1.5.0/docs/guide/misc/…
  • @Ramon:我在问题的最后添加了一些细节,请看一下。谢谢
  • 在这种情况下,您可能想尝试使用Thread#interrupt() 的解决方案。否则,这取决于您正在使用的库的详细信息。也许您可以将下载所在的 OutputStream 替换为 OutputStream 子类,该子类在达到超时后调用 write 时会引发异常。

标签: java timeout executorservice


【解决方案1】:

一般来说,没有可靠的方法可以让单独的线程退出。特别是,在任务外部超时后,没有可靠的方法来中断和停止您的任务。您需要做的是让任务自己负责在时间用完后停止。根据他们所做的,您也许可以将此行为抽象为一个超类,例如:

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() 并执行任务的单个“步骤”。

【讨论】:

  • 我在问题的最后添加了一些细节,请看一下。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    从我的角度来看,我认为这些东西需要一些比普通 Java 标准类更强大的基础,这就是为什么我建议使用任何可以为您提供句柄的调度程序基础架构(Quartz 或任何其他项目)(工作标识符)来终止您耗时的任务。

    你可能有这样的事情:

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

    TimeCheckerJob 将是一个永久的工作,通知任何新工作,并检查每个新工作的生存时间......在这项工作中,您必须处理每个工作的开始时间,注意操作系统时钟和不要尝试设置太硬的约束(纳秒纯属虚构)。

    HTH 我的 2 美分 杰罗姆

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-27
      • 2021-09-12
      • 1970-01-01
      • 2016-02-26
      • 2018-06-29
      • 2012-07-11
      • 1970-01-01
      相关资源
      最近更新 更多