How is Java Timer implemented by the computer? - java

The articles on the site related to Timer talk about how to use Timer to program.
I ask a different question.
How does Java perform Timer method?
Since it is said to avoid time-consuming work by not to use while loop to check whether the current time is the required time point, I think Timer is not implemented simply by using while loop to continuously checking and comparing the current time to the desired time point.
Thank you!

I think Timer is not implemented simply by using while loop to continuously
checking and comparing the current time to the desired time point.
YES, IT IS. The only optimization is; it is using priority queue based on nextExecutionTime for tasks.
JavaDoc states
Timer object is a single background thread that is used to
execute all of the timer's tasks, sequentially. Timer tasks should
complete quickly. If a timer task takes excessive time to complete,
it "hogs" the timer's task execution thread. This can, in turn, delay
the execution of subsequent tasks
Timer class contains
TaskQueue which is a priority queue of TimerTasks, ordered on nextExecutionTime.
TimerThread(queue) the timer's task execution thread, which waits (queue.wait()) for tasks on the timer queue.
TimerThread has private void mainLoop() { where continuous while(true) will keep checking the tasks by comparing nextExecutionTime with currentTimeMillis
currentTime = System.currentTimeMillis();
executionTime = task.nextExecutionTime;
if (taskFired = (executionTime<=currentTime)) {
and if it reaches then calling
if (taskFired) // Task fired; run it, holding no locks
task.run();

According for the javadoc
This class does not offer real-time guarantees: it schedules tasks
using the Object.wait(long) method.
If you look in the code you will find a method called main loop. The first couple of lines are copied below.
private void mainLoop() {
while (true) {
try {
And... it uses a while loop inside of it along with Object.wait() to do the waiting.

Related

Behavior of ScheduledExecutorService

I've been wondering about specific case around ScheduledExecutorService in java.
Let,
ScheduledExecutorService = new ScheduledThreadPoolExecutor(2);
service.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
//Some task taking longer than schedule period to finish executing.
}
},initialDelay,period,TimeUnit.SECONDS);
in this case, say period is 4 seconds. When the schedular starts to execute after initialdelay, task will be blocked inside while(true) inifinite loop.
My question is after each 4 seconds does a task get scheduled disregarding the execution(unfinished) of previous round of task? Because if this is the case this code will crash eventually after running out of memory.
Help is appreciated.
Thank you.
From the javadoc of scheduleAtFixedRate():
If any execution of this task takes longer than its period, then
subsequent executions may start late, but will not concurrently
execute.
Meaning the task will be started once, but since it never finishes there won't be other invocations. You'll just be wasting one thread in the pool.
The same applies to scheduleWithFixedDelay() since the delay is counted from the time when the previous execution finishes (and since it doesn't finish, no next execution can happen).

Multithreading Architecture for N Repeating Tasks

I have N tasks, each to be repeated after its own specific delay Interval(N) using a fixed thread pool size that will usually be smaller than N.
Since there will usually be a shortage of threads, preference should be given to executing a different task rather than repeating a recently completed task.
I was thinking of using an outer ThreadPoolExecutor with N nested ScheduledThreadPoolExecutors. I'm not really sure how to go about this in the most optimal way since each of those classes maintains its own internal thread pool.
Besides the use of a PriorityQueue as answered by assylias, you can also solve this architecturally, by having a simple executing ThreadPoolExecutor, and another ScheduledExecutorService, which will insert the tasks after a given delay.
So every task has the executive Runnable, and an insertion Runnable, and will, after successful execution, tell the ScheduledExecutorService to run the insertion Runnable after a given delay, which will then put the task back into the ThreadPoolExecutor.
As code:
// myExecutionTask
void run() {
doSomeWork();
scheduledExecutor.schedule(myInsertionRunnable, 1000, TimeUnit.MILLISECONDS);
}
and
// myInsertionRunnable
void run () {
threadPoolExecutor.execute(myExecutionTask);
}
Effectively this will automatically cycle the tasks in the ThreadPoolExecutor, as those tasks that have already been finished, will be at the end of the queue.
Edit: As discussed in comments, when using the scheduler's fixedRate or fixedDelay functionality on a very busy system, tasks added later might be executed less often than task that have been added earlier, as the system seems to prefer tasks that are already executing when deciding for the next one to run.
In contrast my solution above cycles these tasks properly, although there can be no guarantee on a busy system, that the requested delay is exact. So they might be executed later, but at least always in FIFO order.
You could use a PriorityBlockingQueue and use timestamps to define priorities - something like:
class Task {
AtomicLong lastRun;
Runnable r;
void run() {
r.run();
lastRun.set(System.currentMillis);
}
}
Your ScheduledExecutorService (one thread) can then add the task N to a PriorityQueue every Interval(N).
And you can have a separate consumer running in your FixedThreadPool that takes from the Queue (using a reverse comparator so that the tasks run more recently will have a lower priority).
That is a little sketchy but it should work.

Schedule a single-threaded repeating runnable in java, but skip the current run if previous run is not finished

Sometimes the duration of a repeated task is longer than its period (In my case, this can happen for hours at a time). Think of a repeated task that takes 7 minutes to run and is scheduled to run every 10 minutes, but sometimes takes 15 minutes for each run for a few hours in a row.
The Timer and ScheduledThreadPoolExecutor classes both have a scheduleAtFixedRate method that is usually used for this type of functionality. However, both have the characteristic that they 'try to catch up when they fall behind'. In other words, if a Timer falls behind by a few executions, it builds up a queue of work that will be worked on continuously until it catches back up to the number of runs that would have happened if none of the tasks had taken longer than the specified period. I want to avoid this behavior by skipping the current execution if the previous run is not complete.
I have one solution that involves messing around with the afterExecution method of a pooled executor, recalculating a delay, and rescheduling the runnable with the new delay, but was wondering if there's a simpler way, or if this functionality already exists in a common library somewhere. I know about scheduling with a fixed delay rather than a fixed period, but this will not work for me since it's important to try to execute the tasks at their fixed times. Are there any simpler options than my afterExecution solution?
I think what you want is for the long-running task itself to not run in the ScheduledExecutorService itself, but in a background thread. Then the fixed-rate task will always complete quickly, since it is only used for checking whether to start the actual task in the background (or not, if it's still running from last time).
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
final Runnable actualTask = null;
executorService.scheduleAtFixedRate(new Runnable() {
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private Future<?> lastExecution;
#Override
public void run() {
if (lastExecution != null && !lastExecution.isDone()) {
return;
}
lastExecution = executor.submit(actualTask);
}
}, 10, 10, TimeUnit.MINUTES);
You could use scheduleWithFixedDelay method instead. It's similar but this one does not have a queue for missed runs and instead starts counting again only when the current Runnable was terminated.
The documentation states the reexecution of the Runnable will be scheduled based on the delay parameter:
The delay between the termination of one execution and the commencement of the next.
Make a third class, say called Coordinator. Coordinator has a synchronized startRunning() method which sets isRunning to true and returns true if another thread was not running already. There should also be a synchronized stopRunning method which sets isRunning to false. It returns true if a runnable is already running. You make a single instance of this class and pass a reference to all of the runnables you construct. In the runnable's run method you first call startRunning and check the return to verify that another one isn't running already. Make sure to put the code in run() in a try-finally and call stopRunning from within the finally block.

How to implement a efficient timeout in java

There are n object which perform some actions. After performing an action a timestamp will be updated. Now I want to implement a timeout-thread which verifies if a timestamp is older than for example 60 seconds.
My first solution was to do that with a thread (while-loop + sleep) which is holding a list with all objects including the last timestamp. Now I have the problem that there is a worst-case scenario where the thread needs 59 seconds plus sleep time to decide for a timeout.
I’m searching for a solution like a Timer where it is possible to update the delay time.
Any ideas?
I think using a monitor object with wait/notify is reasonable (you may use Condition with await/signal if you are using JDK >= 5)
idea is simple:
Worker thread:
doYourActualWork();
synchronized(jobFinishedMonitor) {
updateTimestamp();
jobFinishedMonitor.notify();
}
Timeout thread:
synchronized(jobFinishedMonitor) {
while(within60Second(timestamp)) {
jobFinishedMonitor.wait(60);
}
if (within60Second(timestamp)) {
timeoutHappened=true;
}
}
if (timeoutHappened) {
// do timeout handling
}
For the question, it's not clear what you want to do with the timeout. Here I present you two options to implement a lightweight timeout: monitored vs controlled.
Monitored Timeout
For a global timer, you can use the Timer facility from the JDK:
public TimeoutTask implements TimerTask {
List<MonitorableObject> objects;
public TimeoutTask(List<MonitorableObject> objects) {
// make sure you can share this collection concurrently,
// e.g. copyonwritearraylist
this.objects = objects;
}
public void run() {
// objects -> filter(isTimeOut(currentTime)) -> do something
}
}
Timer timer = new Timer();
timer.schedule(new TimeoutTask(myObjectList), 0,60*1000); // repeat each 60secs
There's a similar construction possible using a ScheduledExecutorService:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
// Note that I can use here TimeoutTask b/c TimerTask is a Runnable -
// this is just for the example. You'd better implement a plain runnable.
scheduler.schedule(new TimeoutTask(myObjectList), 60, TimeUnit.SECONDS);
I prefer the ScheduledExecutorService above the Timer facility, as the SchedulerExecutor can hold a pool of threads. Also, the underlying threadpool can be used for other operations invoking scheduledExecutorService.execute(...) for immediate concurrent execution (not scheduled), making it a generic executor facility, rather than a dedicated timer function.
In both cases, you'll need to take special care to safely get the timeout value from your the objects you are monitoring. Typically, you will use a synchronized method in the object to ask for it's timeout status.
Enforced Timeout
The ExecutorService provides you with an API to execute a set of tasks within a given timeout. e.g.
List<Callable<?>> myTasks = ...;
// populate myTasks with Callable`s that wrap your intended execution
ExecutorService executorService = ... ;
List<Future<?>> results = executorService.invokeAll(myTasks, 60, TimeUnit.SECONDS);
After this method returns, you can ask every Future whether it succeeded within the time given.
Interrupt the thread every time you update a timestamp. Then it will loop, find nothing to do, sleep, and if nothing else has happened to the timestamp, expire it. If it gets interrupted a second time, so much the better. And at all times it should never sleep for longer than 60 minus (current time minus the oldest timestamp).

Is Java's Timer task guaranteed not to run concurrently?

new Timer(...).schedule(task)
Is task guaranteed to be run by a single thread at any given time?
From the Javadoc
Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially. Timer tasks should complete quickly. If a timer task takes excessive time to complete, it "hogs" the timer's task execution thread. This can, in turn, delay the execution of subsequent tasks, which may "bunch up" and execute in rapid succession when (and if) the offending task finally completes.
So, yes, you get a new Thread (separate from the caller's thread). Every task in that timer shares the same thread.
There is a single thread per Timer, so the answer to your question is yes
Indeed. They all run on a same background thread corresponded to the Timer object in sequence. BUT two different Timer instances will run (I believe) on different threads, so you have to save reference to a timer object to schedule more tasks sequentialy.

Categories