Why is @Schedule method working with Future blocking other @Schedule methods

I have this class

@Service
@Profile("async")
public class MyServiceImplAsync implements MyService {
..

    @Async
    @Override
    public void printGreetings(String name) {
        //do something and sleep 10 seconds
    }

    @Async
    @Override
    public Future<String> doSomething(String text) {
        //do something and sleep 25 seconds
        return new AsyncResult<String>(text);
    }

}

      

Note that the two methods use @Async

Now I have the following too:

@Component
public class MySchedule {
..
    @Scheduled(cron="*/5 * * * * ?")
    public void schedule(){
        logger.info("Schedule working at {}", simpleDateFormat.format( new Date() ));
        this.myService.printGreetings("Manolito");
    }

    @Scheduled(cron="*/30 * * * * ?")
    public void scheduleFuture(){
        logger.info("Schedule Future working at {}", simpleDateFormat.format( new Date() ));

        try {
            logger.info("{}", this.myService.doSomething("manolito").get(26, TimeUnit.SECONDS));
        } 
        catch (InterruptedException | ExecutionException | TimeoutException e) {
            logger.error("Error: {}, Class: {}", e.getMessage(), e.getClass());
        }
    }

}

      

The method schedule()

should run every 5 seconds and the method scheduleFuture()

should run every 30 seconds.

I am confused with the following situation:

I can see that the method schedule()

runs at rest every 5 seconds, then when it scheduleFuture()

starts running, the method, scheduleFuture()

due to the future get method, remains blocked. I'm fine with this because this is the expected behavior according to the Future API .

I thought:

Only the method needs to be blocked scheduleFuture()

.

problem : I don't understand why the scheduleFuture()

other method is also blocking schedule()

!. I mean, if scheduleFuture()

locked, the parameter is schedule()

also locked !. It cannot start a new cycle or execution. This is until scheduleFuture()

it unlocks.

Why is this happening?

I have two @Scheduled

methods, each calling two different methods annotated with a @Async

bean (same situation if the classMyServiceImplAsync

@Scope("prototype")

Thanks in advance.

+3


source to share


1 answer


Because you are blocking the only thread that is used to schedule these tasks. From @EnableScheduling

:

All of the above scenarios use the default single threaded task executor. When more control is needed, the @Configuration class can implement SchedulingConfigurer. This allows you to access the main ScheduledTaskRegistrar instance.



@Configuration
@EnableScheduling
public class AppConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
    }

    @Bean(destroyMethod="shutdown")
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(100);
    }
}

      

If you have such a problem, it is a good idea to configure the registration framework to display the name of the thread. With log4j, you need to add %t

toPatternLayout

+5


source







All Articles