Reputation: 892
I have a scheduled job which runs every 100 seconds. Sometimes the execution of this method takes a lot of time (which is ok and there is no problem with that). In this situation, the result of the running method is not important to me and I want to re-schedule the job for next 100 second.
What is the best way to force the running job to terminate (return
) after a specific time?
My scheduled code is like below:
@Scheduled(fixedDelay = 100*1000)
fun calculateLastDaysStatistics() {
logger.info("affiliate statistics thread Started Successfully")
val processStartDate = Date()
for (i in 1..prevDaysToConsider) {
logger.info("AdZone-Stats prev days $i")
val yesterday = DateUtility.addDay(Date(), -i)
val startDate = DateUtility.getZeroDayTime(yesterday.time)
val endDate = DateUtility.addDay(startDate, 1)
/* This method is probable to take a lot of time */
calculateStatistics(startDate, endDate)
}
val processLength = (Date().time - processStartDate.time) / 1000
logger.info("affiliate statistics thread finished in " + processLength + "s")
}
Thanks.
Upvotes: 1
Views: 1893
Reputation: 1159
I'm not sure if you are still looking for an answer to this question after the 5 years you've posted this, but I just came across your question and I thought about sharing something that may help you. Using a TimerTask and interrupted on a thread, you can interrupt whatever you want to do with the Scheduler. It is very specific what you are trying to achieve and therefore maybe this very specific solution will help you:
class Timeouts {
internal class TimeOutTask(f: () -> Unit) : TimerTask() {
val thread = Thread(f)
override fun run() {
thread.start()
}
override fun cancel(): Boolean {
super.cancel()
thread.interrupt()
return true
}
}
companion object {
@JvmStatic
fun main(args: Array<String> = emptyArray()) = measureTimeMillis {
val timer = Timer()
val scheduledFunction = { sleep(5000) }
runFunction(timer = timer, timeout = 1000, f = scheduledFunction)
}.let {
println(it)
}
private fun runFunction(timer: Timer, timeout:Long, f: () -> Unit) {
val timeOutTask = TimeOutTask(f)
timer.schedule(timeOutTask, 0)
sleep(timeout)
timeOutTask.cancel()
timer.cancel()
}
}
}
With this you can stop the scheduled job or anything by that matter at exactly the timeout you want. Note that some calls aren't possible to stop and interrupt at exactly the moment you want but using interrupt you'll be on point or fairly on point for most cases and I guess for your case too. The idea would be to call something like this runFunction inside your code like this:
@Scheduled(fixedDelay = 100*1000)
fun calculateLastDaysStatistics() {
runFunction(timer, 100_000) { ... }
}
Upvotes: 1
Reputation: 1078
You can implement a custom Task scheduler using, org.springframework.scheduling.TaskScheduler
instead of Annotation based method.
private final TaskScheduler scheduler;
@Autowired
public SchedulingManager(TaskScheduler scheduler) {
this.scheduler = scheduler;
}
In this case,
ScheduledFuture scheduledeFuture = scheduler.schedule(()->{
....You job goes here..
}, new CronTrigger("*/100 * * * * *"));
You can keep track of the scheduled future to make sure it runs max time intended.
scheduledeFuture.get(100,TimeUnit.SECONDS)
Upvotes: 1
Reputation: 11
Try using Fixed Rate instead of Fixed Delay
Here is the article from Paraschiv.E. The @Scheduled Annotation in Spring. Referred from https://www.baeldung.com/spring-scheduled-tasks
Schedule a Task at a Fixed Rate
@Scheduled(fixedRate = 1000) public void scheduleFixedRateTask() { System.out.println( "Fixed rate task - " + System.currentTimeMillis() / 1000); }
Note that the beginning of the task execution doesn’t wait for the completion of the previous execution.
This option should be used when each execution of the task is independent.
Upvotes: 1