Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Timer schedule vs scheduleAtFixedRate?

public class MyTimerTask extends TimerTask{

    @Override
    public void run() {
        int i = 0; 
        try {
            Thread.sleep(100000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Run Me ~" + ++i);
        System.out.println("Test");

    }

}

Case 1 :-
    TimerTask task = new MyTimerTask();
    Timer timer = new Timer();
    timer.schedule(task, 1000,6000); // line 1
    System.out.println("End"); // here is bebug point. 

My Expectation of schedule() method (as per my understanding given in javadocs where each execution is scheduled once previous task execution is completed) that two threads should be created after line 1.

One for timer which spawns another thread for tasks. Once first task thread dies another will be created and son on. But at debug point , i just see one thread corresponding to Timer. Why not thread for tasks which implement Runnable?

Case 2 :-

    TimerTask task = new MyTimerTask();
    Timer timer = new Timer();
    timer.scheduleAtFixedRate(task, 1000,6000); // line 1
    System.out.println("End"); // here is bebug point. 

My Expectation of scheduleAtFixedRate() method(as per my understanding given in javadocs where each execution is scheduled relative to the scheduled execution time of the initial execution) that around 17 threads(dont pay much attention to 17. It can be more or less to that. But it should be greater than 2 ) should be created after line 1.

One for timer which should spawn 16 other thread corresponding two each task. At first task sleeps for 100 second, Timer should create another thread corresponding to next task and similarly for other task. But at debug point , i just see one thread corresponding to Timer. Here also i can see sequential execution of task. Why not 17 threads?

UPDATE :- As per ScheduleAtFixedRate javadocs , each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up. what does that mean? To me it gives impression, if second task is due even first task is not completed, then timer will create new thread for due task. Is n't it?

like image 309
M Sach Avatar asked Dec 30 '13 17:12

M Sach


People also ask

What is scheduleAtFixedRate?

The scheduleAtFixedRate(TimerTask task, long delay, long period) is the method of Timer class. It is used to schedule the given task again and again in fixed rate of execution. It will begin after the specified delay.

What is the relationship between Timer and TimerTask?

Timer and TimerTask are java util classes that we use to schedule tasks in a background thread. Basically, TimerTask is the task to perform, and Timer is the scheduler.

How to use scheduleAtFixedRate in java?

The scheduleAtFixedRate(TimerTask task,long delay,long period) method is used to schedule the specified task for repeated fixed-rate execution, beginning after the specified delay.

What is the delay and period in Timer () in java?

delay - delay in milliseconds before task is to be executed. period - time in milliseconds between successive task executions. IllegalStateException - if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.


2 Answers

The javadoc for Timer says

Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially.

Basically it holds a queue of tasks to which it adds when you schedule them. It uses one thread to iterate over the queue and execute the tasks.

like image 35
Sotirios Delimanolis Avatar answered Oct 08 '22 23:10

Sotirios Delimanolis


Timer uses the Active Object pattern under the hood, so there is only ever a single thread being used and scheduling a new task on the timer adds that task to the thread's tasks queue.

The timer thread keeps track of all the tasks in it's queue and sleeps until the next task is scheduled. Then, it wakes up and executes the task itself by invoking task.run() directly, meaning that it does not spawn another thread to execute the code.

This also means that if you schedule two tasks to execute at the same time then, true to the Active Object pattern, they will be executed sequentially (one after another) on the same thread of control. This means the second task will execute after it's scheduled time (but probably not by much).

Now, to unequivocally answer your question, here is the scheduling logic from Timer.class that schedules the next time that the task should be run again (from lines 262-272 here):

// set when the next task should be launched
if (task.fixedRate) {
    // task is scheduled at fixed rate
    task.when = task.when + task.period;
} else {
    // task is scheduled at fixed delay
    task.when = System.currentTimeMillis()
            + task.period;
}

// insert this task into queue
insertTask(task);

task.fixedRate is set to true if you use one of the timer.scheduleAtFixedRate() methods and is set to false if you use one of the timer.schedule() methods.

task.when is the "time" (ticks) that the task was scheduled to run.

task.period is the interval you passed to the timer.schedule*() method.

So, from the code we can see that if you use a fixed rate then a repeating task will be scheduled to run relative to when it was first started. If you don't use a fixed rate, then it is scheduled to run relative to when it was last run (which will drift relative to a fixed rate, unless your task is never delayed and takes less than one tick to execute).

This also means that if a task falls behind and it is on a fixed rate, then Timer will keep rescheduling the task for immediate execution until it catches up to the total number of times it should have ran over a given period.

So if you have a task, say a ping() that you schedule to run at a fixed rate every 10ms and there is temporary blocking in the ping() method to where it takes 20ms to execute, then the Timer will call ping() again immediately after the previous call finished, and it will keep doing so until the given rate is achieved.

like image 165
Matt Klein Avatar answered Oct 09 '22 01:10

Matt Klein