简体   繁体   English

如何精确地以每秒几千的固定速率安排任务

[英]How to accurately schedule a task with a fixed rate of several per second

I currently use 我目前使用

 ScheduledFuture<?> schedulerFuture = scheduler.scheduleAtFixedRate(taskMaker, 0 , period, TimeUnit.MICROSECONDS);                
 ScheduledFuture<?> timerFuture = timer.schedule(timeAnalyser, time, TimeUnit.MICROSECONDS);

for executing many tasks per second, also asynchron in several threads.The problem is, that I get inaccuracies. 每秒执行许多任务,也可能在多个线程中异步。问题是我不准确。 For example, when I want to execute 3 Tasks in the first Thread in one second, 7 in the second Thread and 5 in the third Thread, sometimes i get 4, 7, 6 or 3, 6, 6. It is not that the processor cant make it when using bigger numbers, but the more tasks I want to execute per second the greater the inaccuracies become. 例如,当我想在一秒钟内在第一个线程中执行3个任务,在第二个线程中执行7个任务,在第三个线程中执行5个任务时,有时我会得到4,7,6或3,6,6。当使用更大的数字时,处理器无法做到这一点,但是我每秒要执行的任务越多,误差就越大。 Maybe it's because the timer (which stops the taskMaker ) is started not at the exactly same time as the taskMaker ? 也许是因为timer (停止taskMaker )启动的时间不是与taskMaker完全相同的时间?

Any changing suggestions? 有任何变化的建议吗? Is it the right way anyway to use the SchedulesExecutorService for executing tasks with such a high frequency? 无论如何,使用SchedulesExecutorService以如此高的频率执行任务是正确的方法吗?

The implementations of the various ExecutorService use a working queue, of which purpose is that as long a work job is available use the next available thread to execute it, if no Thread is available (is busy), than a new one is created (in the limit of the specified available threads, if this number is reached, than it will wait for a thread to become available), so you don't have any control over the threads ... and especially not on which tasks to be executed. 各种ExecutorService的实现都使用一个工作队列,其目的是,只要有一个工作作业可用,就使用下一个可用线程执行该工作队列(如果没有可用的线程(繁忙)),则创建一个新的线程。指定的可用线程数的限制(如果达到此数目,它将等待一个线程可用),因此您对线程没有任何控制权,尤其是无法执行哪些任务。

For such an Executor , you should consider implementing your own Executor, that might use a Executors.newSingleThreadScheduledExecutor() for your frequency (3, 7 and 5). 对于这样的Executor ,您应该考虑实现自己的Executor,对于您的频率( Executors.newSingleThreadScheduledExecutor()和5),可以使用Executors.newSingleThreadScheduledExecutor() )。 eg: 例如:

ScheduledExecutorService exec1 = Executors.newSingleThreadScheduledExecutor();
ScheduledExecutorService exec2 = Executors.newSingleThreadScheduledExecutor();
ScheduledExecutorService exec3 = Executors.newSingleThreadScheduledExecutor();

exec1.scheduleAtFixedRate(task, 0, 1000 / 3, TimeUnit.MILLISECONDS);
exec2.scheduleAtFixedRate(task, 0, 1000 / 7, TimeUnit.MILLISECONDS);
exec2.scheduleAtFixedRate(task, 0, 1000/5, TimeUnit.MILLISECONDS);

From the javadoc 从javadoc

If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute. 如果此任务的任何执行花费的时间超过其周期,则后续执行可能会开始得较晚,但不会同时执行。

I think you might want to manage the timings yourself using schedule rather than scheduleAtFixedRate (eg calculate the delay after one task executes and schedule the next task for that exact delay period). 我认为您可能想使用schedule而不是scheduleAtFixedRate自己管理计时(例如,计算一个任务执行后的延迟,并为该确切的延迟时间安排下一个任务的时间)。

Also note that unless you are doing lots of IO, you should keep the pool size to the number of processors on the server (eg Executors.newScheduledThreadPool(numberOfCpus) ) 另请注意,除非您要进行大量IO操作,否则应将池大小保持为服务器上处理器的数量(例如Executors.newScheduledThreadPool(numberOfCpus)

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

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