如何以固定速率安排任务,持续时间长于速率?
How to schedule a task at fixed rate with a duration longer than the rate?
我正在尝试安排一个需要 ~2.25 秒的任务,每个 运行 second.Thus 我知道 3 个线程应该足以处理负载。我的代码如下所示:
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4);
scheduler.scheduleAtFixedRate(new Streamer(), 0, 1000, TimeUnit.MILLISECONDS);
有趣的是,这类似于延迟为 0 的 scheduledAtFixedDelay(线程每 ~2.25 秒完成一次)。
我知道,如果线程 运行 迟到了,那么 scheduleAtFixedRate 可能会迟到。但是不应该给执行者一个更大的线程池来解决这个问题吗?
我可以通过编写 3 个执行程序每 3 秒启动一次的代码来轻松解决这个问题,但这会给管理带来不必要的困难。
这个问题有更简单的解决方案吗?
scheduledExecutor 自动防止任务执行重叠。所以你的后续执行将被延迟到前一个执行完成之后。
Docs:
"If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute."
因此您需要安排 3 个任务,其中 1) InitDelay 0 秒,2) InitDelay 1 秒,3) InitDelay 2 秒,每个任务的周期为 3 秒.
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4);
final Streamer sharedStreamer = new Streamer();
scheduler.scheduleAtFixedRate(sharedStreamer, 0, 3, TimeUnit.SECONDS);
scheduler.scheduleAtFixedRate(sharedStreamer, 1, 3, TimeUnit.SECONDS);
scheduler.scheduleAtFixedRate(sharedStreamer, 2, 3, TimeUnit.SECONDS);
请注意,如果有大量同步代码,使用共享资源执行可能会导致执行时间延长。
可以使用threadPool和scheduler来实现这个效果:
创建一个 fixedThreadPool(或其他满足您需求的线程池),假设有 4 个线程 - 线程数应基于单个任务执行所消耗的时间以及执行任务的速率任务被安排,基本上numberOfThreads = avgExecTimeOfSingleTaks * frequency + someMargin;
然后创建调度线程,每一秒(或其他需要的周期)都会向fixedThreadPool队列添加一个作业,然后任务可以重叠。
这种解题方式还有额外的惊喜:
如果您的任务开始花费的时间超过 2.25 秒,或者您想以更高的频率执行它们,那么您所要做的就是向线程池添加一些线程,而使用其他答案,您需要重新计算和重新安排一切。所以这个方法给你更清晰和更容易维护的方法。
我正在尝试安排一个需要 ~2.25 秒的任务,每个 运行 second.Thus 我知道 3 个线程应该足以处理负载。我的代码如下所示:
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4);
scheduler.scheduleAtFixedRate(new Streamer(), 0, 1000, TimeUnit.MILLISECONDS);
有趣的是,这类似于延迟为 0 的 scheduledAtFixedDelay(线程每 ~2.25 秒完成一次)。
我知道,如果线程 运行 迟到了,那么 scheduleAtFixedRate 可能会迟到。但是不应该给执行者一个更大的线程池来解决这个问题吗?
我可以通过编写 3 个执行程序每 3 秒启动一次的代码来轻松解决这个问题,但这会给管理带来不必要的困难。
这个问题有更简单的解决方案吗?
scheduledExecutor 自动防止任务执行重叠。所以你的后续执行将被延迟到前一个执行完成之后。
Docs:
"If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute."
因此您需要安排 3 个任务,其中 1) InitDelay 0 秒,2) InitDelay 1 秒,3) InitDelay 2 秒,每个任务的周期为 3 秒.
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4);
final Streamer sharedStreamer = new Streamer();
scheduler.scheduleAtFixedRate(sharedStreamer, 0, 3, TimeUnit.SECONDS);
scheduler.scheduleAtFixedRate(sharedStreamer, 1, 3, TimeUnit.SECONDS);
scheduler.scheduleAtFixedRate(sharedStreamer, 2, 3, TimeUnit.SECONDS);
请注意,如果有大量同步代码,使用共享资源执行可能会导致执行时间延长。
可以使用threadPool和scheduler来实现这个效果:
创建一个 fixedThreadPool(或其他满足您需求的线程池),假设有 4 个线程 - 线程数应基于单个任务执行所消耗的时间以及执行任务的速率任务被安排,基本上numberOfThreads = avgExecTimeOfSingleTaks * frequency + someMargin;
然后创建调度线程,每一秒(或其他需要的周期)都会向fixedThreadPool队列添加一个作业,然后任务可以重叠。
这种解题方式还有额外的惊喜:
如果您的任务开始花费的时间超过 2.25 秒,或者您想以更高的频率执行它们,那么您所要做的就是向线程池添加一些线程,而使用其他答案,您需要重新计算和重新安排一切。所以这个方法给你更清晰和更容易维护的方法。