I'm using spring-boot #Scheduled annotation with fixedDelay in milliseconds as documented in javadoc:
Execute the annotated method with a fixed period in milliseconds between the end of the last invocation and the start of the next.
Code:
#Scheduled(fixedDelay=1000)
public void task() {
LOG.info("START: " + System.currentTimeInMillis());
....do some work here...
LOG.info("END: " + System.currentTimeInMillis());
}
And sometimes I get such output that time between previous task end and next task starts is less than 1000ms for about 2-30 milliseconds.
Is it normal due to some granularity or why is it happening? Is there any guaranties about this delta value?
There are different ways in which you can use #Scheduled annotation.
According to the documentation:
The fixedRate invokes the method every t ms but the time delay is measured from the start of the invocation. If t ms are passed and the method is still in execution then the next invocation will wait for it to finish and will invoke right after the first one. Try putting Thread.sleep(3000) in your method. I think that your method is taking about 950ms to complete.
If you want to wait after finishing the execution you can use fixedDelay.
Obviously it cannot be guaranteed since you're most likely not on a real time system. Depending on what the CPU(s) do at the moment it can vary like that. It's quite hard to do something like that actually on most PC's due to the OS scheduling calls and so on (unless you have direct access to the CPU/GPU but even then)
How #Scheduled(fixedDelay=1000) works is, it will run this void method every 1000 ms(If this task finish execution < 1000 ms or this will run asynchronously). If > 1000ms it the execution task will get into a task queue in the Executor service used. There is no connection with the end of task and the start of next task but a connection with the start of a task and start of a next task.
Related
I want to understand about the ideal value of timeout in awaitTermination() method for executorservice. How should we decide the ideal timeout? Does it harm if we use one day as the timeout?
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
suppose I am loading data from one database to another database. Sometimes it may slow down because of network issues and even the number of documents to upload may also increase. So it becomes a little difficult to judge the max time. So in that scenario, if I use one day as a timeout (Actually, I want to use awaitTermination() without a timeout from executorService side). What exactly are the disadvantages of this?
What is the downside of awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS)?
because anyways, executorservice will terminate once the tasks are done
This depends on how long a task can consume.
How long in the worst case you longest task will take?
Lets say it will take in worst case 1 min. Then take 2 min.
You simply calculate worst case time plus a buffer.
You simply don't wont that the started job is canceled without reason because you can get a data loss.
If you are working e.g. on a queue with confirmation and you confirm only if your job is done, you can terminate immediately because on next start and after timeout your worker gets the task again. (But be carefully. If you servere restarts you can end up in a loop)
I have a Spring Boot application that uses a #Scheduled annotation with a fixed delay. The annotation is used in different classes with different delays. However, at midnight every day all scheduled tasks stop running.
Does anyone know why this might be happening? I can't find any explanation online.
(I am using version 2.0.2.RELEASE of Spring Boot and 5.0.6.RELEASE of Spring Core.)
Thanks in advance!
I'm not sure what do you mean about stopping running.
But the first work you need to do is starting your schedules on different threads and put them into a queue.
If stopping means suspending for a while,then you create a new schedule that make other schedules sleep some time at midnight.Maybe the new schedule should have be started when the thread are sleeping,and the way to prevent is to make sure only one schedule(I mean same kind of schedule) could be put in the queue at the same time.
If you just mean kill all other schedule at midnight,you just need to start your midnight schedules and kill others.
So sorry about my poor English,hope this could help you.
#Scheduled(fixedDelay = 1000)
void scheduleFixedDelayTask() {
System.out.println(
"Fixed delay task - " + System.currentTimeMillis() /
1000);
}
In this case, the duration between the end of last execution and the start of next execution is fixed. The task always waits until the previous one is finished.
This option should be used when it’s mandatory that the previous execution is completed before running again.
So maintain the delay such a way that the previous execution completed.
Hope it helps.
Thanks to everyone who replied.
As it turns out, this was not an issue with Spring. It appeared the tasks stopped because the logs stopped. What really happened was that our scripts that tail the logs were not smart enough to handle log files that roll at midnight (face palm).
Right now I have two threads running in my program. One constantly tries to read input from the user, and the other watches for a timeout. A timeout occurs if the user does not send any input in a given amount of time. The two threads look like this:
User input thread
while(true){
if(in.hasNextLine()){
processLine(in.nextLine());
timeLastRecieved = System.currentTimeMillis();
}
}
Timeout thread
while(true){
//Check for a timout
if(timeLastRecieved+timeoutDuration <= System.currentTimeMillis())
timeUserOut();
else{
//Sleep until it is possible for a timeout to occur
Thread.sleep((timeLastSent+timeoutDuration) - System.currentTimeMillis());
}
}
As of now I have these thread separated, but I could combine them like this...
while(true){
if(in.hasNextLine()){
processLine(in.nextLine());
timeLastRecieved = System.currentTimeMillis();
}
//Check for a timout
if(timeLastRecieved+timeoutDuration <= System.currentTimeMillis())
timeUserOut();
}
But I really don't need to check for a timeout that frequently. So should I combine the threads and check for a timeout too often, or should I have two threads. I am not as worried about performance as I am proper coding etiquette. If it means anything the timeout duration in something like 15 minutes long.
EDIT: Just want to point out that in the version with two thread I am sleeping, but in the combined version I never sleep the thread. This obviously causes the if statement that checks for a timeout to run more then necessary.
To summarize my comments: I don't think a separate thread to check for timeouts is necessary.
Reasons:
You'd need to share information like timeLastRecieved between them, which could be more complex than wanted (e.g. AFAIK in some cases access to long values is not atomic).
From your description it seems that polling for user input and timeout (no input provided in time) are closely related, thus the polling thread could check for the timeout as well. That doesn't mean it has to handle the timeout too, just reporting it somewhere or calling some timeout handler might be better design.
It is easier to read and understand since updating timeLastRecieved and checking for a timeout is handled in the same place.
Since there is no inter-thread communication nor coordination needed (there are no threads that need to communicate) it probably is more robust as well.
A few hints on checking for the timeout:
You should calculate the timeout threshold when you update timeLastReceived and then only check agains the current time instead of calculating it in every iteration.
You might want to calculate the timeout threshold before processing the input in order not to have it depend on the processing time as well.
Finally, there are alternative approaches like using java.util.Timer. Here you could simply schedule a timeout task which is executed when the timeout should occur. That task then would check if the timeout really happened and if not it just returns.
To handle new input before the timeout occured you could use at least two approaches:
Cancel the current timeout task, remove it from the timer and schedule a new one.
If there is already a scheduled timeout task then don't schedule a new one but wait for the current one to run. The current one then checks for the timeout and if none happened it schedules a new task (or itself) for the current anticipated timeout (note that this would require some inter-thread communcation so be careful here).
You need to have two threads - one waiting for data coming in through the InputStream / Reader, and one that's watching the time to see if the time elapsed as taken too long. The only way to do it with 1 thread would be to sleep for a segment of the timeout period and then poll for data periodically. But that's less efficient than having a separate thread dedicated to reading from your InputStream/Reader.
You may want to check out Timeout as a generic option for implementing a timeout
I want to get the delay between the time a job was supposed to execute and the time it actually executed for the most recent execution. For example, if a job was supposed to fire at 8pm and it actually fired at 8.10pm, the result should be 10 minutes.
I know that I can use Trigger.getPreviousFireTime() to get the last time it actually executed, but I can't see any way to get the corresponding scheduled time (e.g. 8pm for the example above), is this possible?
Inside your job use the following code:
#Override
public void execute(final JobExecutionContext context) {
long diffInMillis =
new Date().getTime() - context.getScheduledFireTime().getTime();
//...
}
As you probably guessed context.getScheduledFireTime() is the time when job was suppose to run (ideally the difference should be close to 0).
Note that if your job is late more than 10 minutes (configurable) it might not fire at all - it depends on your misfire instruction set up.
Would you please explain to me the exact mean of the StatefulJob in quartz and it's difference with none StatefulJob?
StatefulJob interface, provides 2 things,
first: only one job will be run any time
second: in (SimpleTriggerBean) you will not worry about your job running duration. it means that the next run will be done after delay time after ending of previous one.
StatefulJob guarantees only one job will be running at one time. For example, if you schedule your job to run every 1 minute, but your job took 5 minutes to complete, then the job will not be run again until the previous job has completed.
This is useful to make sure there is only one job running at any given time.
The next job will be run on the next schedule, not immediately after the previous job completed.
jobDetail.getJobDataMap().put("type","FULL");
This line is will decide we are using statefull or non-statefull.
If we are passing the argument then it will be statefull.
With out statefull there is no way to pass the arguments in execute method
In state full while execution time if we modify any value then the execution job will be lost it wont re-triggered at simultaneous process time.
Only one job will execute at a time the second will be sleep until the first one is completed.
In multi scheduling process the second job argument will be share to first job at run time. this is one type of disadvantage in multi scheduling process.