I am using the ScheduledThreadPoolExecutor to execute periodic tasks.
It is essential that the execution be periodic, not with fixed delay.
I encountered the following problem: consider a period of 1 minute for a task. If the task takes 5 minutes to execute (e.g. because of a temporary network problem), the missed executions get queued up and dispatched immediately after the task finishes. Is there a way to get rid of the accumulated executions that were missed?
I tried using the remove method, but it removes the task completely, not only a specific execution.
Thanks
There might be a better way, but you could have your task reschedule itself. That way, one execution will always run 1 minute after the previous execution has finished:
final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable yourTask = new Runnable() {
#Override
public void run() {
//do your stuff
scheduler.schedule(this, 1, TimeUnit.MINUTES);
}
};
scheduler.schedule(yourTask, 1, TimeUnit.MINUTES);
EDIT
If you want your task to run exactly at hh:mm:00 (exact minute) you can replace the code by
long millisToNextMinute = 60000 - System.currentTimeMillis() % 60000;
scheduler.schedule(this, millisToNextMinute, TimeUnit.MILLISECONDS);
You can build this logic into the task. Have the task record the last time it ran. Every time it starts, it should check whether enough time has passed since the last run. If not, then it should exit without doing any work.
In CronScheduler, there are SkippingToLatest methods (see Javadocs, "Skipping to latest runs" section that are particularly designed to handle this problem for you:
Duration syncPeriod = Duration.ofMinutes(1);
CronScheduler cron = CronScheduler.create(syncPeriod);
cron.scheduleAtFixedRateSkippingToLatest(0, 1, TimeUnit.MINUTES, runTimeMillis -> {
// Do your task
});
Related
I have a ScheduledExecutorService that I am using to run a method updateIndex() every one minute. However, if changes to resources are made during the one minute between the last refresh and the next refresh, I would like to have updateIndex() called immediately, and then have the executor service resume it's normal schedule; i.e. next update will take place in one minute. However, I haven't seen anything in the documentation to suggest there is the capability to do this. Any ideas?
public static void updateIndex() {
Runnable runnable = () -> {
//Do your logic here
};
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(runnable, 0, 1, TimeUnit.MINUTES);
}
According to JavaDocs
java.util.concurrent.ScheduledExecutorService.scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay then initialDelay+period, then initialDelay + 2 * period, and so on. If any execution of the task encounters an exception, subsequent executions are suppressed. Otherwise, the task will only terminate via cancellation or termination of the executor. If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
scheduleAtFixedRate() returns a ScheduledFuture which is a Future which has the cancel method you're looking for.
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)
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.
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)
I'm interested in using ScheduledExecutorService to spawn multiple threads for tasks if task before did not yet finish. For example I need to process a file every 0.5s. First task starts processing file, after 0.5s if first thread is not finished second thread is spawned and starts processing second file and so on. This can be done with something like this:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(4)
while (!executor.isShutdown()) {
executor.execute(task);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// handle
}
}
Now my question: Why I can't do it with executor.scheduleAtFixedRate?
What I get is if the first task takes longer, the second task is started as soon as first finished, but no new thread is started even if executor has pool of threads. executor.scheduleWithFixedDelay is clear - it executes tasks with same time span between them and it doesn't matter how long it takes to complete the task. So probably I misunderstood ScheduledExecutorService purpose.
Maybe I should look at another kind of executor? Or just use code which I posted here? Any thoughts?
I've solved the problem by launching a nested anonymous runnable in each scheduled execution:
final ScheduledExecutorService service = Executors.newScheduledThreadPool(POOL_SIZE);
final Runnable command = new SlowRunnable();
service.scheduleAtFixedRate(
new Runnable() {
#Override
public void run() {
service.execute(command);
}
}, 0, 1, TimeUnit.SECONDS);
With this example there will be 1 thread executing at every interval a fast instruction, so it will be surely be finished when the next interval is expired. The remaining POOL_SIZE-1 threads will be executing the SlowRunnable's run() in parallel, which may take longer time than the duration of the single interval.
Please note that while I like this solution as it minimize the code and reuse the same ScheduledExecutorService, it must be sized correctly and may not be usable in every context: if the SlowRunnable is so slow that up to POOL_SIZE jobs get executed together, there will be no threads to run the the scheduled task in time.
Also, if you set the interval at 1 TimeUnit.NANOSECONDS it will probably became too slow also the execution of the main runnable.
One of the scheduleAtFixedRate methods is what you're looking for. It starts a task in a thread from the pool at the given interval, even if previous tasks haven't finished. If you're running out of threads to do the processing, adjust the pool size constraints as detailed in the ThreadPoolExecutor docs.