Search code examples
javaspring-bootschedulerspring-scheduled

Put some delay between two batch jobs


I have created two batch jobs and both jobs have initial delay of 20 seconds. Now I want to put some delay between those 2 jobs. If Job1 is running then Job2 has to wait for some seconds and then execute only if Job1 is done similarly if Job2 is running then Job1 has to wait for some seconds and then execute only if Job2 is done.

@Component
public class Job1{

    @Scheduled(fixedRate = 20000)
    public void execute() {
        //business logic
    }
}

@Component
public class Job2{

    @Scheduled(fixedRate = 20000)
    public void execute() {
        //business logic
    }
}

Solution

  • You can achieve the behaviour by having the jobs run in a single synchronized method, for example by introducing a class which has a method to execute a synchronized method, i.e.

    @Component
    class SingleThreadJobRunner {
        synchronized void run(Runnable runnable) {
            runnable.run();
        }
    }
    

    A full working example which utilizes this class across different @Scheduled-methods:

    @EnableScheduling
    @SpringBootApplication
    public class Test {
        public static void main(String[] args) {
            SpringApplication.run(Test.class, args);
        }
    }
    
    @Component
    class SingleThreadJobRunner {
        synchronized void run(Runnable runnable) {
            runnable.run();
        }
    }
    
    @Component
    @RequiredArgsConstructor
    class Job1 {
        private final SingleThreadJobRunner singleThreadJobRunner;
    
        @Scheduled(fixedRate = 1000)
        public void execute() {
            singleThreadJobRunner.run(() -> {
                System.out.print("job 1 started - ");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("job 1 completed");
    
            });
        }
    }
    
    @Component
    @RequiredArgsConstructor
    class Job2 {
        private final SingleThreadJobRunner singleThreadJobRunner;
    
        @Scheduled(fixedRate = 1500)
        public void execute() {
            singleThreadJobRunner.run(() -> {
                System.out.print("job 2 started - ");
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("job 2 completed");
            });
        }
    }
    

    Varying rates and sleep-times were used to show that the jobs never overlap. If you need the delay between the methods which you mention in your question, this could be added to the run()-method.