代码之家  ›  专栏  ›  技术社区  ›  ip696

如何用具体的调度程序启动@scheduled方法?

  •  3
  • ip696  · 技术社区  · 6 年前

    我有调度程序:

    @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;
    }
    

    方法:

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

    第二种方法:

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

    如何配置每个 @Scheduled 方法与具体的调度?

    如果我像这样实现它:

    @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);
        }
    

    关于未使用和使用的调度程序任务执行器:

    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] 
    

    但使用了 TaskExecutor 为什么?

    3 回复  |  直到 6 年前
        1
  •  2
  •   Ori Marko    6 年前

    DR

    根据 Spring scheduling 它们是TaskScheduler抽象的不同实现

    1. 作为实现的ThreadPoolTaskScheduler:

      线程池任务调度程序,可以在不需要外部线程管理时使用。在内部,它委托给ScheduledExecutorService实例。ThreadPoolTaskScheduler实际上也实现了Spring的TaskExecutor接口,因此单个实例可以尽快用于异步执行,以及计划的、可能重复执行的执行。

    2. @调度为任务调度的注释支持

    @scheduled注释可以与触发器元数据一起添加到方法中。

    另请参见 answer for best way to schedule task ,投票最多:

    在Spring中调度任务的最简单方法是在SpringManagedBean中创建由@scheduled注释的方法。

        2
  •  1
  •   dpr    6 年前

    当使用 @Scheduled 注释:对于不同的bean,没有现成的支持来使用不同的线程池。您可以配置线程池以通过实现 SchedulingConfigurer 在你的 @Configuration 班级。

    我认为您编辑后的实现应该可以工作。你可能只需要打电话 threadPoolTaskScheduler.initialize() 创建这样的调度程序之后:

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

    这将创建调度器的内部执行器,它使用实际执行的内容。

        3
  •  0
  •   Rohit    6 年前

    您需要实现 SchedulingConfigurer 在config类中并重写它 configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) 方法。在重写的方法中,注册 ThreadPoolTaskScheduler :

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