美文网首页
SpringBoot——@Scheduled的自定义周期性线程池

SpringBoot——@Scheduled的自定义周期性线程池

作者: Hughman | 来源:发表于2021-03-31 08:51 被阅读0次

    关注微信公众号:CodingTechWork,一起学习进步。

    问题

      在使用Spring中的@Scheduled注解设置定时任务时,遇到这样2个问题:

    1. 定时任务未按时执行,现象是延后了一段时间才执行定时任务。
    2. 多个定时任务有时间重叠时,无法并发调度执行。

    分析

      出现上面问题现象的根因是Spring的定时任务默认是单线程执行,所以会在某些场景下造成阻塞。当然我们可以通过@Async注解来异步执行这些并发的@Scheduled注解的定时任务,而@Async线程池容量是100,当超过100个线程并发执行时,则剩下的定时任务会等待之前的线程释放,不会自行扩容。
      既然@Async是个定值大小的线程池,还是有出现定时任务延时执行的问题,所以下面我们可以通过其他方式来自定义线程池大小。

    解决方式

      通过自定义配置线程池来解决问题。

    package com.andya.selfcode.conf;
    
    import com.google.common.util.concurrent.ThreadFactoryBuilder;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.scheduling.annotation.SchedulingConfigurer;
    import org.springframework.scheduling.config.ScheduledTaskRegistrar;
    
    import java.util.concurrent.*;
    
    
    
    /**
     * @author Andya
     * @create 2021-03-31
     */
    @Slf4j
    @Configuration
    public class ScheduleConfig implements SchedulingConfigurer {
    
        //自定义线程池大小,可配置。代码中默认10个
        @Value("${threadPool.schedule.coreSize: 10}")
        public int SCHEDULE_CORE_SIZE;
    
        //自定义线程池名称
        public static final String THREAD_NAME_WITH_SCHEDULE = "schedule-thread-%d";
        
        @Override
        public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
    //        scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(SCHEDULE_CORE_SIZE));
            scheduledTaskRegistrar.setScheduler(this.buildSchedulerThreadPool());
            System.out.println("Scheduler threadpool core_size: " + SCHEDULE_CORE_SIZE);
        }
    
        /**
         * Spring的@Scheduled的自定义周期性线程池
         * @return
         */
        @Bean(value = "scheduleThreadPool")
        public ExecutorService buildSchedulerThreadPool() {
            ThreadFactory threadFactory = new ThreadFactoryBuilder()
                    .setNameFormat(THREAD_NAME_WITH_SCHEDULE).build();
    
            /**
             * 1. CallerRunsPolicy :    这个策略重试添加当前的任务,他会自动重复调用 execute() 方法,直到成功。
             2. AbortPolicy :         对拒绝任务抛弃处理,并且抛出异常。
             3. DiscardPolicy :       对拒绝任务直接无声抛弃,没有异常信息。
             4. DiscardOldestPolicy : 对拒绝任务不抛弃,而是抛弃队列里面等待最久的一个线程,然后把拒绝任务加到队列。
             不写则为默认的AbortPolicy策略。
             */
            ScheduledExecutorService threadPool = new ScheduledThreadPoolExecutor(
                    SCHEDULE_CORE_SIZE,
                    threadFactory);
            return threadPool;
        }
    }
    
    

    相关文章

      网友评论

          本文标题:SpringBoot——@Scheduled的自定义周期性线程池

          本文链接:https://www.haomeiwen.com/subject/kthohltx.html