I'm writing an Android application that records audio every 10 minutes. I am using a Timer to do that. But what is the difference between schedule and scheduleAtFixedRate? Is there any performance benefit in using one over the other?
The difference is best explained by this non-Android documentation:
Fixed-rate timers (scheduleAtFixedRate()) are based on the starting time (so each iteration will execute at startTime + iterationNumber * delayTime).
In fixed-rate execution, 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."
Fixed-delay timers (schedule()) are based on the previous execution (so each iteration will execute at lastExecutionTime + delayTime).
In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution. If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well.
Aside from this, there is no difference. You will not find a significance performance difference, either.
If you are using this in a case where you want to stay synchronized with something else, you'll want to use scheduleAtFixedRate(). The delay from schedule() can drift and introduce error.
A simple schedule() method will execute at once while scheduleAtFixedRate() method takes and extra parameter which is for repetition of the task again & again on specific time interval.
by looking at syntax :
Timer timer = new Timer();
timer.schedule( new performClass(), 30000 );
This is going to perform once after the 30 Second Time Period Interval is over. A kind of timeoput-action.
Timer timer = new Timer();
//timer.schedule(task, delay, period)
//timer.schedule( new performClass(), 1000, 30000 );
// or you can write in another way
//timer.scheduleAtFixedRate(task, delay, period);
timer.scheduleAtFixedRate( new performClass(), 1000, 30000 );
This is going to start after 1 second and will repeat on every 30 seconds time interval.
According to java.util.Timer.TimerImpl.TimerHeap code
// this is a repeating task,
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;
}
--
java.util.Timer.schedule(TimerTask task, long delay, long period)
will set task.fixedRate = false;
java.util.Timer.scheduleAtFixedRate(TimerTask task, long delay, long period)
will set task.fixedRate = true;
btw Timer doesn't work when screen is off.
You should use AlarmManager.
There is sample:http://developer.android.com/training/scheduling/alarms.html
In case of schedule it only executes once when the appropriate times came. On the other hand scheduleAtFixedRate has an extra parameter period which contains amount of time in milliseconds between subsequent executions.
More info can be find here
http://developer.android.com/reference/java/util/Timer.html#schedule(java.util.TimerTask, long)
Related
I'm currently trying to use a Timer to execute an action at set intervals.
I've taken a snippet from Stack Overflow, however it did not have an explanation, and I'm struggling to figure out what it's parameters mean.
Could someone please explain to me the parameters for the method?
It's namely the last 2 parameters, 5000, 5000 which I don't understand.
TimerTask damageInterval = new TimerTask() {
public void run() {
playerInfoPanel.health -= monsterDamage - playerInfoPanel.defenceLevel;
}
};
inflictDamage.schedule(damageInterval, 5000, 5000);
JavaDocs are your friend
public void schedule(TimerTask task,
long delay,
long period)
Schedules the specified task for repeated fixed-delay execution,
beginning after the specified delay. Subsequent executions take place
at approximately regular intervals separated by the specified period.
In fixed-delay execution, each execution is scheduled relative to the
actual execution time of the previous execution. If an execution is
delayed for any reason (such as garbage collection or other background
activity), subsequent executions will be delayed as well. In the long
run, the frequency of execution will generally be slightly lower than
the reciprocal of the specified period (assuming the system clock
underlying Object.wait(long) is accurate).
Fixed-delay execution is appropriate for recurring activities that
require "smoothness." In other words, it is appropriate for activities
where it is more important to keep the frequency accurate in the short
run than in the long run. This includes most animation tasks, such as
blinking a cursor at regular intervals. It also includes tasks wherein
regular activity is performed in response to human input, such as
automatically repeating a character as long as a key is held down.
Parameters: task - task to be scheduled. delay - delay in milliseconds before task is to be executed. period - time in
milliseconds between successive task executions.
I have a requirement where I need to run a task every 15 seconds.
I have seen several articles suggesting to use ScheduledExecutorService rather than TimerTask which I'm doing.
Runnable runnable = new Runnable() {
#Override
public void run() {
//Some task
}
};
ScheduledExecutorService scheduler = Executors
.newScheduledThreadPool(5);
scheduler
.scheduleAtFixedRate(runnable, 0, 15000, TimeUnit.MILLISECONDS);
Th problem is that the runnable does not execute in between randomly, maybe for 1...2..5 minutes sometimes.
I have my try catch in place and there is no exception or error.
I added a date-time log
time2 : 2015-12-10T11:28:00.000+04:00
time2 : 2015-12-10T11:28:00.000+04:00
time2 : 2015-12-10T11:29:00.000+04:00
time2 : 2015-12-10T11:31:00.000+04:00
time2 : 2015-12-10T11:31:00.000+04:00
As you can see the runnable was not executed for 11:30
Why is this skip? The timer is doing the same task every time & I think it's unlikely that delay in the previous task causes this delay.
I tried increasing the pool-size from 1 to 5, but still the same result.
If this is a thread issue...Than I know I have certain options which I can use instead of newScheduledThreadPool. Like newCachedThreadPool ,newFixedThreadPool ,newSingleThreadScheduledExecutor .
All I want to do is execute a certain task every 15 seconds & execute it every time even if the previous task took long to complete or had any exception.
How can I achieve it?
Java doesn't give you real-time guarantees on time. I'd advise you to log both starting and ending time of your job. There is statement for scheduleAtFixedRate apidoc
If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
check that it is not your case.
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html#scheduleAtFixedRate(java.lang.Runnable,%20long,%20long,%20java.util.concurrent.TimeUnit)
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?
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.
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.
The timer class creates one thread per instance of the timer class and this thread do all tasks scheduled Timer#schedule or Timer#scheduleAtFixRate.
So, as you ovserved, the timer creates only one thread.
A task would have came start time before the preciding task has finished, then the follwing task has waited until the preciding task has finished.
So, Timer "never" create another thread although the preciding task hasn't finished and the time the following task has to start has come.
So, I advise you that:
if you want to schedule tasks and do the tasks on time whether a preciding task has finished or not, use ScheduledThreadPoolExecutor instead of Timer.
And though if you do not want, it's prefer to use ScheduledThreadPoolExecutor than Timer because for one thing, tasks scheduled by Timer would never have done if a task would have threw RuntimeException or Error.
Schedule will not execute the missed task if the start time is in the past.
scheduleAtFixedRate will execute the missed tasks if the start time is in the past.For the missed tasks, the start time will be calculated based last task's end time. When missed tasks are executed fully, the new normal tasks' start time will be calculated based on last task's start time.
BR Sanchez
for(Date timerDate1=startDate; timerDate1<=cal3.add(cal3.DATE,7);startDate=cal3.add(cal3.DATE,1))
{
long period=60*60*1000;
Timer timer = new Timer();
timer.schedule(new MyTask(),timerDate,period);
cal3.add(cal3.DATE,1);
}
Use timer.scheduleAtFixedRate
void java.util.Timer.scheduleAtFixedRate(TimerTask task, long delay, long period)
scheduleAtFixedRate
public void scheduleAtFixedRate(TimerTask task,
long delay,
long period)
Schedules the specified task for repeated fixed-rate execution, beginning after the specified delay. Subsequent executions take place at approximately regular intervals, separated by the specified period. In fixed-rate execution, 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." In the long run, the frequency of execution will be exactly the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate).
Fixed-rate execution is appropriate for recurring activities that are sensitive to absolute time, such as ringing a chime every hour on the hour, or running scheduled maintenance every day at a particular time. It is also appropriate for recurring activities where the total time to perform a fixed number of executions is important, such as a countdown timer that ticks once every second for ten seconds. Finally, fixed-rate execution is appropriate for scheduling multiple repeating timer tasks that must remain synchronized with respect to one another.
Parameters: task - task to be scheduled. delay - delay in milliseconds before task is to be executed. period - time in milliseconds between successive task executions. Throws: IllegalArgumentException - if delay is negative, or delay + System.currentTimeMillis() is negative. IllegalStateException - if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
Instead of a for-loop, use a single Timer, and pass your task to one of the scheduleAtFixedRate methods of Timer, with a period of TimeUnit.DAYS.toMillis(1).
Your task class should be constructed with a starting Date and the class should store that date in a field. In the class's run method, use a Calendar to check whether the current time, minus 7 days, is later than the task's start date, and if it is, call cancel() and return immedately.
Suppose that I have the general scheduled task shown below
Timer t = new Timer();
TimerTask listenHandover = new TimerTask() {
public void run()
{
// Some methods that can possibly take more than 1 second to execute
}
};
t.schedule(listenHandover, 1000 , 1000);
As the comment says, what happens if the task takes more than 1 second to execute ? Will the currentlly running one will be restarted when the next one is scheduled ? or do the tasks have their own threads ? Hope it was clear. Thanks
If task takes more than 1 second, subsequent tasks will be queued up until offending one completes.
As per javadoc
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.