【问题标题】:Make other threads wait until ScheduledExecutorService completes all tasks让其他线程等到 ScheduledExecutorService 完成所有任务
【发布时间】:2021-07-11 08:08:12
【问题描述】:

主要目标是使用 ScheduledExecutorService 运行一个方法,并等待其所有任务完成后再恢复主线程。

我在自定义 Scheduler 类中创建了一个实用方法,它接受任何 Runnable:

public void scheduleFunction(Runnable function) {
    final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    final ScheduledFuture<?> producerHandle = scheduler.scheduleAtFixedRate(function, initialDelay, interval, MILLISECONDS);
    scheduler.schedule(() -> { producerHandle.cancel(true); }, timeout, MILLISECONDS);
}

当我需要在调度模式下执行它的方法时,在其他类中使用它:

public void sendToKafka() {
  Scheduler.scheduleFunction(this::produce);
}

这很好,除了一件事。 当主线程到达 sendToKafka() 时,它会调用调度器来调度一个函数。主线程继续运行,同时Scheduled函数开始工作。

实际结果: 两个线程同时运行

预期结果: 当调度程序线程启动时,主线程停止并等待调度程序完成执行

我怎样才能做到这一点?

【问题讨论】:

标签: java multithreading scheduled-tasks


【解决方案1】:

由于你在这个方法中创建和放弃了ScheduledExecutorService,你应该调用shutdown()来支持及时释放资源。如果您这样做,您可以致电awaitTermination 等待所有待处理作业的完成。

public void scheduleFunction(Runnable function) {
    final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    final ScheduledFuture<?> producerHandle
        = scheduler.scheduleAtFixedRate(function, initialDelay, interval, MILLISECONDS);
    scheduler.schedule(() -> {
        producerHandle.cancel(true);
        scheduler.shutdown();
    }, timeout, MILLISECONDS);
    try {
        scheduler.awaitTermination(Long.MAX_VALUE, MILLISECONDS);
    } catch (InterruptedException ex) {
        Thread.currentThread().interrupt();
    }
}

注意,当你不需要中断时,你可以简单地使用

public void scheduleFunction(Runnable function) {
    final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    scheduler.scheduleAtFixedRate(function, initialDelay, interval, MILLISECONDS);
    scheduler.schedule(() -> scheduler.shutdown(), timeout, MILLISECONDS);
    try {
        scheduler.awaitTermination(Long.MAX_VALUE, MILLISECONDS);
    } catch (InterruptedException ex) {
        Thread.currentThread().interrupt();
    }
}

因为关闭ScheduledExecutorService 意味着停止重新安排工作;只有在执行过程中才会完成,awaitTermination 会等待它。

【讨论】:

  • 不幸的是,没有一个解决方案不起作用。在此示例中,计划任务从不运行。主线程也被冻结了。
  • 由于任务的调度方式与您的原始代码没有什么不同,它们的运行方式应该完全相同。 This runs smoothly
  • 是的,现在工作正常,我使用了一些同步 - 这就是它不起作用的原因。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-21
  • 2014-10-05
  • 2019-06-22
  • 1970-01-01
  • 1970-01-01
  • 2011-06-05
  • 1970-01-01
相关资源
最近更新 更多