简体   繁体   English

如何以固定的速率安排任务的持续时间长于该速率?

[英]How to schedule a task at fixed rate with a duration longer than the rate?

I'm trying to schedule a task that requires ~2.25 sec to be run every second.Thus I know 3 threads should be enough to handle the load. 我正在尝试安排一个需要每秒运行约2.25秒的任务,因此我知道3个线程应该足以处理负载。 My code looks like this: 我的代码如下所示:

private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4);
scheduler.scheduleAtFixedRate(new Streamer(), 0, 1000, TimeUnit.MILLISECONDS);

interestingly this behaves like scheduledAtFixedDelay with a delay of 0 (threads finish every ~2.25 sec). 有趣的是,它的行为类似于scheduleAtFixedDelay,延迟为0(线程每〜2.25秒完成一次)。

I know, that scheduleAtFixedRate can be late if a thread runs late. 我知道,如果线程延迟运行,则scheduleAtFixedRate可能会延迟。 But shouldn't giving the executor a larger threadpool solve this problem? 但是,不应该给执行者更大的线程池来解决此问题吗?

I could easily circumnvent the problem by coding 3 executors to start every 3 seconds, but that would make administration unnecessarily difficult. 我可以通过编码3个执行器每3秒启动一次来轻松解决该问题,但这会使管理变得不必要地困难。

Is there an easier solution to this problem? 有解决这个问题的简便方法吗?

You can use threadPool and scheduler to achieve this effect: 您可以使用threadPool和Scheduler实现此效果:

  1. Create a fixedThreadPool (or other that will fullfill your needs), let say with 4 threads - the number of threads should be based on the time single task consumes to execute and the rate at which the tasks are scheduled, basically numberOfThreads = avgExecTimeOfSingleTaks * frequency + someMargin; 创建一个fixedThreadPool(或满足您需求的其他线程),用4个线程说-线程数应基于单个任务执行所消耗的时间和计划任务的速率,基本上numberOfThreads = avgExecTimeOfSingleTaks *频率+ someMargin;

  2. then create scheduler thread, that every second (or other desired period) will add a job to the fixedThreadPool queue, then the tasks can overlap. 然后创建调度程序线程,即每隔一秒钟(或其他期望的时间)将作业添加到fixedThreadPool队列中,然后任务可以重叠。

This way of solving the problem has additional adventage: 解决问题的这种方式具有更多的优势:

If your tasks start to take longer than 2.25 sec, or you would like to execute them with greater frequency, then all you have to do is to add some threads to the threadPool, whereas using the other answer, you need to recalculate and reschedule everything. 如果您的任务开始耗时超过2.25秒,或者您想以更高的频率执行它们,那么您要做的就是向threadPool添加一些线程,而使用其他答案,则需要重新计算并重新安排所有时间。 So this approch gives you clearer and easier to maintenance approach. 因此,此方法为您提供了更清晰,更易于维护的方法。

The scheduledExecutor automatically prevents overlapping of Task executions. ScheduledExecutor自动防止任务执行重叠。 So your subsequent executions will be delayed until after the previous one has finished. 因此,您的后续执行将延迟到上一个执行完成之后。

Docs : 文件

"If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute. " “如果此任务的任何执行花费的时间超过其周期,那么后续执行可能会延迟启动, 但不会同时执行。

So you need to schedule 3 Tasks with 1) InitDelay 0 secs, 2) InitDelay 1 secs, 3) InitDelay 2 secs and for each of them a Period of 3 secs. 因此,您需要计划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);

Mind that execution with the shared resource could lead to extended execution time, if there are large portions of synchronized code. 请注意,如果有大部分同步代码,使用共享资源执行可能会导致执行时间延长。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM