javaspringcron

What is the expected behaviour of spring @scheduled cron when jobs would overlap?


I have a job that runs once an hour, and I'm using Spring's @scheduled cron to schedule it. If the job takes more than an hour, I understand from How to prevent overlapping schedules in Spring? that the next job won't kick off while the first job is running.

Does this mean that it will kick off after the first job has completed, or has it missed its chance?

If I have one job that takes 10 hours, will all the missed cron jobs queue up and then execute one by one when the first job completes after 10 hours, or will just the first job run?


Solution

  • By default, execution is blocking and single-threaded, which means they will not run concurrently. If you want jobs to run simultaneously, you can annotate the method as @Async as well. You may also want to look at the different Executors.

    If you're using fixedDelay like in the sample question you provided, the next job will only kick off AFTER the current one is over, plus the delay. So if your job takes 10 hours and you have a fixedDelay of 5000, the next job will kick off 5 seconds after the 10 hour one.

    If you're using fixedRate then the next scheduled event will be queued up to run, but not skipped, as per the documentation:

    If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.

    If you are simply using cron, then the jobs will be queued and executed in turn (similar to fixedRate). You can test this with a simple method (below is in Groovy, but can use plain Java too):

        int i = 0
    
        @Scheduled(cron = '* * * * * * ')
        void test() {
            if (i < 5)
                Thread.sleep(10000)
    
            i += 1
            println '------------------------' + i // No values skipped
        }
    

    You'll note that every number is printed; e.g. no cycle is ever skipped.