Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accuracy of ScheduledExecutorService on normal OS / JVM

I use ScheduledExecutorService.scheduleAtFixedRate to run a daily task, like this:

executor.scheduleAtFixedRate(task, d, 24L * 3600 * 1000, TimeUnit.MILLISECONDS);

(d is the initial delay in milliseconds).

The executor is created by Executors.newSingleThreadScheduledExecutor() and runs multiple tasks, but they are all scheduled a few hours apart, and take at most a few minutes.

I know that ScheduledExecutorService makes no guarantees about accuracy, and I'd need a real-time OS and JVM to get that. That is not a requirement for my task, though.

I noticed that on a Windows 2003 Server, using JDK 1.7.0_03, the task slips by almost 10 seconds per day. That makes about 5 minutes per month, which is acceptable for my application. I'll probably have to implement re-scheduling anyway, because I want the task to run at a specific local time, and so I'll have to take care of DST myself. The service runs for long periods of time - half a year without restart is not that unusual.

Still, I think that an inaccuracy of 10 sec/day is rather high for a mostly idle system, and I wonder if I should be prepared for even worse behavior.

So my question is about your experiences with scheduleAtFixedRate. Are the 10 sec/day normal? Will I get better or worse accuracy in other environments (our customers also use Linux and Solaris servers)? Or are the 10 seconds an indication that something is amiss in our environment?

like image 842
Chris Avatar asked Oct 22 '22 20:10

Chris


1 Answers

For a very long running task, it is not too surprising. Another problem you have is that it uses nanoTime() which is not synchronized with NTP or the like. This can result in drift with the wall clock.

One way to avoid this is to schedule repeatedly as you suggest. The repeating tasks actually reschedule themselves (which is why they cannot throws an exception, see below) You can have a one shot task which reschedules itself at the end, using the wall clock time and taking into account day list savings.

BTW: I would make sure you catch an exceptions or even Throwable thrown. If you don't your task will stop, possibly silently (unless you are looking at the Future object returned)

What I do is cheat a little. I have a task which wakes every 1 - 10 seconds and checks if it needs to run and if not returns. The overhead is usually trivial if you don't have thousands of tasks and it's much simpler to implement.

like image 197
Peter Lawrey Avatar answered Oct 29 '22 18:10

Peter Lawrey