How can I start @Scheduled method with concrete scheduler?

Viewed 233

I have scheduler:

@Bean("one")
ThreadPoolTaskScheduler taskScheduler(){
    ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
    threadPoolTaskScheduler.setPoolSize(5);
    threadPoolTaskScheduler.setAwaitTerminationSeconds(60);
    threadPoolTaskScheduler.setThreadNamePrefix("Test-");
    return threadPoolTaskScheduler;
}

@Bean("two")
ThreadPoolTaskScheduler taskScheduler2(){
    ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
    threadPoolTaskScheduler.setPoolSize(50);
    threadPoolTaskScheduler.setAwaitTerminationSeconds(60);
    threadPoolTaskScheduler.setThreadNamePrefix("Test2-");
    return threadPoolTaskScheduler;
}

And method:

@Scheduled(fixedRate = 1000L)
public void test() {

And Second method:

@Scheduled(fixedRate = 1000L)
public void test2() {

How can I configure each @Scheduled method with concrete scheduler?

If I implement it like this:

@Slf4j
@Component
public class MyScheduler {

    private final ThreadPoolTaskScheduler taskSchedulerFirst;
    private final ThreadPoolTaskScheduler taskSchedulerSecond;
    private final TestBean testBean;

    public MyScheduler(@Qualifier("first") ThreadPoolTaskScheduler taskSchedulerFirst, @Qualifier("second")ThreadPoolTaskScheduler taskSchedulerSecond, TestBean testBean) {
        this.taskSchedulerFirst = taskSchedulerFirst;
        this.taskSchedulerSecond = taskSchedulerSecond;
        this.testBean = testBean;
    }

    @PostConstruct
    public void test() {
        taskSchedulerFirst.scheduleAtFixedRate(testBean::test, 1000L);
        taskSchedulerSecond.scheduleAtFixedRate(testBean::test2, 1000L);
    }

Bouth schedulers not used and used TaskExecutor:

2018-09-05 11:10:30.812  INFO 10724 --- [TaskExecutor-41] com.example.scheduling.TestBean          : hz
2018-09-05 11:10:31.747  INFO 10724 --- [TaskExecutor-43] com.example.scheduling.TestBean          : hz
2018-09-05 11:10:31.748  INFO 10724 --- [TaskExecutor-46] com.example.scheduling.TestBean          : hz2
2018-09-05 11:10:32.747  INFO 10724 --- [TaskExecutor-45] com.example.scheduling.TestBean          : hz
2018-09-05 11:10:32.748  INFO 10724 --- [TaskExecutor-48] com.example.scheduling.TestBean          : hz2
2018-09-05 11:10:33.747  INFO 10724 --- [TaskExecutor-47] 

But used TaskExecutor why?

3 Answers

TL;DR No

According to Spring scheduling they are different implementations of TaskScheduler abstraction

  1. ThreadPoolTaskScheduler as implementation:

    ThreadPoolTaskScheduler, can be used whenever external thread management is not a requirement. Internally, it delegates to a ScheduledExecutorService instance. ThreadPoolTaskScheduler actually implements Spring's TaskExecutor interface as well, so that a single instance can be used for asynchronous execution as soon as possible as well as scheduled, and potentially recurring, executions.

  2. @Scheduled as annotation support for task scheduling

The @Scheduled annotation can be added to a method along with trigger metadata.

See also answer for best way to schedule task , most voted:

The simplest way to schedule tasks in Spring is to create method annotated by @Scheduled in spring managed bean.

When using the @Scheduled annotation there is no out-of-the-box support to use different thread pools for different beans. You can configure the thread pool to be used by implementing SchedulingConfigurer in your @Configuration class.

I think the implementation after your edit should work. You probably only need to call threadPoolTaskScheduler.initialize() directly after creating the scheduler like this:

@Bean("two")
ThreadPoolTaskScheduler taskScheduler2(){
    ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
    threadPoolTaskScheduler.initialize(); // initialize scheduler
    threadPoolTaskScheduler.setPoolSize(50);
    threadPoolTaskScheduler.setAwaitTerminationSeconds(60);
    threadPoolTaskScheduler.setThreadNamePrefix("Test2-");
    return threadPoolTaskScheduler;
}

This will create the scheduler's internal executor, that is used the actually execute stuff.

You need to implement the SchedulingConfigurer in config class and override it's configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) method. In the overridden method register your ThreadPoolTaskScheduler:

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
    ...

        scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
    }
Related