zoukankan      html  css  js  c++  java
  • SpringBoot——@Scheduled的自定义周期性线程池解决任务延时执行问题

    关注微信公众号: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;
        }
    }
    
    
    烧不死的鸟就是凤凰
  • 相关阅读:
    heapq of python
    array of python
    Unittest of Python
    事件驱动型工作流 vs 引擎型工作流
    airflow
    WPF 调试触发器
    WPF 使用Popup和TreeView实现树状下拉框
    Oracle : ORA 00933: SQL command not properly ended
    PostgreSQL && PostGIS
    基于ArcGIS开发3D立方体空间关系判断
  • 原文地址:https://www.cnblogs.com/Andya/p/14599860.html
Copyright © 2011-2022 走看看