【问题标题】:ScheduledExecutorService: how to wait for all tasks to finish then execute more tasksScheduledExecutorService:如何等待所有任务完成然后执行更多任务
【发布时间】:2019-10-11 13:40:23
【问题描述】:

我的代码是这样的:

ScheduledExecutorService executor = Executors.newScheduledThreadPool(8);

//complex code that call this multiple times too add tasks:
executor.schedule(() -> { doRealTask(); }, 0, TimeUnit.MICROSECONDS);

//drain the pool on some condition, e.g. meets tasks that can't be parallelized:
executor.shutdown();//without this, awaitTermination won't return since all the threads in the pool will be paused, not terminated
executor.awaitTermination(1000000, TimeUnit.SECONDS);

//continue to add more tasks:
executor.schedule(...);

java.util.concurrent.RejectedExecutionException 在最后一个代码上抛出。原因似乎是 executor 已关闭。但是没有“startAgain”功能。显然创建一个新的 ScheduledExecutorService 是可行的,但我觉得我使用了错误的解决方案。

如何在 Java 中实现?

【问题讨论】:

  • 为什么不使用调用 schedule 时返回的期货?您可以将它们存储在列表中并循环它们,然后使用 .get 实质上加入您的任务。
  • 你到底想做什么?
  • @tmarwen 将大量任务发送到池中由多个线程执行,当遇到一些无法并行化的任务时,先等待前一个任务完成然后将其发送到池中。

标签: java task


【解决方案1】:

将您的未来存储在列表中,然后使用 get 有效地加入。

List<Future<?>> futures = new ArrayList<>();

futures.add(executor.schedule(() -> { doRealTask(); }, 0, TimeUnit.MICROSECONDS));

而不是关闭。

for(Future<?> future: futures){
    future.get();
}

futures.clear();

现在您需要处理异常,并且可能在获取时包含超时。

【讨论】:

    【解决方案2】:

    关闭状态是不可逆的,所以如果需要,只需要创建一个新的执行器。没有其他方法可以重用前一个。但是,如果要再次创建它,为什么需要关闭它呢?如果它有太多任务并且您可以牺牲它们来支持新任务,那么为每个任务配置合理的超时并配置池本身(例如,池和任务队列大小)是有意义的。

    Executor.schedule(() -&gt; { doRealTask(); }, 0, TimeUnit.MICROSECONDS); 的每次调用都会返回ScheduledFuture 实例,您可以将其存储起来,稍后再处理结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-17
      • 1970-01-01
      • 2017-04-14
      • 2020-05-13
      • 1970-01-01
      相关资源
      最近更新 更多