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).
Related
I was trying some codes to implement a scheduled task and came up with these codes .
import java.util.*;
class Task extends TimerTask {
int count = 1;
// run is a abstract method that defines task performed at scheduled time.
public void run() {
System.out.println(count+" : Mahendra Singh");
count++;
}
}
class TaskScheduling {
public static void main(String[] args) {
Timer timer = new Timer();
// Schedule to run after every 3 second(3000 millisecond)
timer.schedule( new Task(), 3000);
}
}
My output :
1 : Mahendra Singh
I expected the compiler to print a series of Mahendra Singh at periodic interval of 3 s but despite waiting for around 15 minutes, I get only one output...How do I solve this out?
Advantage of ScheduledExecutorService over Timer
I wish to offer you an alternative to Timer using - ScheduledThreadPoolExecutor, an implementation of the ScheduledExecutorService interface. It has some advantages over the Timer class, according to "Java in Concurrency":
A Timer creates only a single thread for executing timer tasks. If a
timer task takes too long to run, the timing accuracy of other
TimerTask can suffer. If a recurring TimerTask is scheduled to run
every 10 ms and another Timer-Task takes 40 ms to run, the recurring
task either (depending on whether it was scheduled at fixed rate or
fixed delay) gets called four times in rapid succession after the
long-running task completes, or "misses" four invocations completely.
Scheduled thread pools address this limitation by letting you provide
multiple threads for executing deferred and periodic tasks.
Another problem with Timer is that it behaves poorly if a TimerTask throws an unchecked exception. Also, called "thread leakage"
The Timer thread doesn't catch the exception, so an unchecked
exception thrown from a TimerTask terminates the timer thread. Timer
also doesn't resurrect the thread in this situation; instead, it
erroneously assumes the entire Timer was cancelled. In this case,
TimerTasks that are already scheduled but not yet executed are never
run, and new tasks cannot be scheduled.
And another recommendation if you need to build your own scheduling service, you may still be able to take advantage of the library by using a DelayQueue, a BlockingQueue implementation that provides the scheduling functionality of ScheduledThreadPoolExecutor. A DelayQueue manages a collection of Delayed objects. A Delayed has a delay time associated with it: DelayQueue lets you take an element only if its delay has expired. Objects are returned from a DelayQueue ordered by the time associated with their delay.
Use timer.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.
public void schedule(TimerTask task,long delay)
Schedules the specified task for execution after the specified delay.
you want:
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.
timer.scheduleAtFixedRate( new Task(), 1000,3000);
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.
I was trying some codes to implement a scheduled task and came up with these codes .
import java.util.*;
class Task extends TimerTask {
int count = 1;
// run is a abstract method that defines task performed at scheduled time.
public void run() {
System.out.println(count+" : Mahendra Singh");
count++;
}
}
class TaskScheduling {
public static void main(String[] args) {
Timer timer = new Timer();
// Schedule to run after every 3 second(3000 millisecond)
timer.schedule( new Task(), 3000);
}
}
My output :
1 : Mahendra Singh
I expected the compiler to print a series of Mahendra Singh at periodic interval of 3 s but despite waiting for around 15 minutes, I get only one output...How do I solve this out?
Advantage of ScheduledExecutorService over Timer
I wish to offer you an alternative to Timer using - ScheduledThreadPoolExecutor, an implementation of the ScheduledExecutorService interface. It has some advantages over the Timer class, according to "Java in Concurrency":
A Timer creates only a single thread for executing timer tasks. If a
timer task takes too long to run, the timing accuracy of other
TimerTask can suffer. If a recurring TimerTask is scheduled to run
every 10 ms and another Timer-Task takes 40 ms to run, the recurring
task either (depending on whether it was scheduled at fixed rate or
fixed delay) gets called four times in rapid succession after the
long-running task completes, or "misses" four invocations completely.
Scheduled thread pools address this limitation by letting you provide
multiple threads for executing deferred and periodic tasks.
Another problem with Timer is that it behaves poorly if a TimerTask throws an unchecked exception. Also, called "thread leakage"
The Timer thread doesn't catch the exception, so an unchecked
exception thrown from a TimerTask terminates the timer thread. Timer
also doesn't resurrect the thread in this situation; instead, it
erroneously assumes the entire Timer was cancelled. In this case,
TimerTasks that are already scheduled but not yet executed are never
run, and new tasks cannot be scheduled.
And another recommendation if you need to build your own scheduling service, you may still be able to take advantage of the library by using a DelayQueue, a BlockingQueue implementation that provides the scheduling functionality of ScheduledThreadPoolExecutor. A DelayQueue manages a collection of Delayed objects. A Delayed has a delay time associated with it: DelayQueue lets you take an element only if its delay has expired. Objects are returned from a DelayQueue ordered by the time associated with their delay.
Use timer.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.
public void schedule(TimerTask task,long delay)
Schedules the specified task for execution after the specified delay.
you want:
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.
timer.scheduleAtFixedRate( new Task(), 1000,3000);
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.
I was trying some codes to implement a scheduled task and came up with these codes .
import java.util.*;
class Task extends TimerTask {
int count = 1;
// run is a abstract method that defines task performed at scheduled time.
public void run() {
System.out.println(count+" : Mahendra Singh");
count++;
}
}
class TaskScheduling {
public static void main(String[] args) {
Timer timer = new Timer();
// Schedule to run after every 3 second(3000 millisecond)
timer.schedule( new Task(), 3000);
}
}
My output :
1 : Mahendra Singh
I expected the compiler to print a series of Mahendra Singh at periodic interval of 3 s but despite waiting for around 15 minutes, I get only one output...How do I solve this out?
Advantage of ScheduledExecutorService over Timer
I wish to offer you an alternative to Timer using - ScheduledThreadPoolExecutor, an implementation of the ScheduledExecutorService interface. It has some advantages over the Timer class, according to "Java in Concurrency":
A Timer creates only a single thread for executing timer tasks. If a
timer task takes too long to run, the timing accuracy of other
TimerTask can suffer. If a recurring TimerTask is scheduled to run
every 10 ms and another Timer-Task takes 40 ms to run, the recurring
task either (depending on whether it was scheduled at fixed rate or
fixed delay) gets called four times in rapid succession after the
long-running task completes, or "misses" four invocations completely.
Scheduled thread pools address this limitation by letting you provide
multiple threads for executing deferred and periodic tasks.
Another problem with Timer is that it behaves poorly if a TimerTask throws an unchecked exception. Also, called "thread leakage"
The Timer thread doesn't catch the exception, so an unchecked
exception thrown from a TimerTask terminates the timer thread. Timer
also doesn't resurrect the thread in this situation; instead, it
erroneously assumes the entire Timer was cancelled. In this case,
TimerTasks that are already scheduled but not yet executed are never
run, and new tasks cannot be scheduled.
And another recommendation if you need to build your own scheduling service, you may still be able to take advantage of the library by using a DelayQueue, a BlockingQueue implementation that provides the scheduling functionality of ScheduledThreadPoolExecutor. A DelayQueue manages a collection of Delayed objects. A Delayed has a delay time associated with it: DelayQueue lets you take an element only if its delay has expired. Objects are returned from a DelayQueue ordered by the time associated with their delay.
Use timer.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.
public void schedule(TimerTask task,long delay)
Schedules the specified task for execution after the specified delay.
you want:
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.
timer.scheduleAtFixedRate( new Task(), 1000,3000);