Hamid Ghasemi
Hamid Ghasemi

Reputation: 892

Java stop scheduled task if it takes more than a specific time

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

Answers (3)

João Esperancinha
João Esperancinha

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

aravindaM
aravindaM

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

bachkilan
bachkilan

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


  1. 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

Related Questions