Springboot @Schedule + 线程池配置可以轻松实现多个任务之间异步, 但是同一任务同步执行

Springboot @Scheduled 默认是单线程的, 也就是说当我们定义了多个定时任务时,如果有本应该是相同时间触发的定时任务, 会进行排队, 如果某个定时任务执行时间过长, 就会导致其他定时并未按照设置时间来触发执行。 异步任务可以部分解决这个问题, 在定时任务上再加上@Asyns注解,定时任务就会被作为异步任务多线程执行。

@Async
@Scheduled(cron = "*/5 * * * * ?")
public void mapDiagnosisExecutor() throws InterruptedException {
    SimpleDateFormat sdf = new SimpleDateFormat("YYYY/MM/dd HH:mm:ss.SSS");
    log.info("定时任务Diagnosis执行时间:" + sdf.format(new Date()));
    Thread.sleep(10000);
}

但是异步任务同样存在一个问题,如果任务执行顺序对结果没有影响,则可以用异步任务解决。但是如果同样的任务必须同步执行(例如定时扫表数据进行相关处理),但又不希望不同的定时任务之间也排队等待,则可以通过一下方式解决。

spring:
  task:
    scheduling:
      pool:
        size: 20
      thread-name-prefix: task-scheduling-

当然也可以通过@Configuration配置


    @Bean
    public ThreadPoolTaskScheduler testExecutor() {
        ThreadPoolTaskScheduler threadPoolTaskScheduler  = new ThreadPoolTaskScheduler();
        // 配置线程池大小
        threadPoolTaskScheduler.setPoolSize(20);
        // 设置线程名
        threadPoolTaskScheduler.setThreadNamePrefix("task-scheduling-");
        // 设置等待任务在关机时完成
        //    threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
        // 设置等待终止时间
       // threadPoolTaskScheduler.setAwaitTerminationSeconds(60);

        return threadPoolTaskScheduler;
    }

@Scheduled注解的定时任务默认是单线程, 但是可以通过配置线程池,实现多线程处理。而且这种方式的多线程是不同任务之间的多线程,相同任务还是会排队执行。

定时任务:

@Slf4j
@Component
public class TestTask {

  
    @Scheduled(cron = "*/5 * * * * ?")
    public void mapDiagnosisExecutor() throws InterruptedException {
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY/MM/dd HH:mm:ss.SSS");
        log.info("定时任务Diagnosis执行时间:" + sdf.format(new Date()));
        Thread.sleep(10000);        //模拟定时任务执行时长
    }

    @Scheduled(cron = "*/5 * * * * ?")
    public void mapDrugExecutor() {
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY/MM/dd HH:mm:ss.SSS");
        log.info("定时任务mapDrug执行时间:" + sdf.format(new Date()));
    }

}

log如下:

2022-04-07 09:24:19 [main] [com.dch.biz.util.cache.StatisticsCache] [INFO] - start to load statistics cache data.
2022-04-07 09:24:20 [task-scheduling-1] [com.dch.biz.task.TestTask] [INFO] - 定时任务Diagnosis执行时间:2022/04/07 09:24:20.004
2022-04-07 09:24:20 [task-scheduling-2] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:24:20.004
 Time:2139 ms - ID:com.dch.biz.dao.TMpSourceDao.queryHomePageInfo
Execute SQL:select count(src_count) as srcCount,sum(src_count) as totalNum , src_hospital as srcHospital, task_id as taskId, concept_type as conceptType, map_status as mapStatus, map_result as mapResult from t_mp_source GROUP BY src_count, src_hospital, task_id, concept_type, map_status, map_result

2022-04-07 09:24:21 [main] [com.dch.biz.util.cache.StatisticsCache] [INFO] - end to load statistics cache data.
2022-04-07 09:24:21 [main] [com.dch.ApplicationEventListener] [INFO] - 应用已启动完成
四月 07, 2022 9:24:21 上午 org.apache.catalina.core.ApplicationContext log
信息: Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-04-07 09:24:25 [task-scheduling-2] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:24:25.007
2022-04-07 09:24:30 [task-scheduling-3] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:24:30.003
2022-04-07 09:24:35 [task-scheduling-2] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:24:35.005
2022-04-07 09:24:35 [task-scheduling-4] [com.dch.biz.task.TestTask] [INFO] - 定时任务Diagnosis执行时间:2022/04/07 09:24:35.005
2022-04-07 09:24:40 [task-scheduling-3] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:24:40.010
2022-04-07 09:24:45 [task-scheduling-5] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:24:45.010
2022-04-07 09:24:50 [task-scheduling-1] [com.dch.biz.task.TestTask] [INFO] - 定时任务Diagnosis执行时间:2022/04/07 09:24:50.014
2022-04-07 09:24:50 [task-scheduling-6] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:24:50.014
2022-04-07 09:24:55 [task-scheduling-2] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:24:55.016
2022-04-07 09:25:00 [task-scheduling-7] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:25:00.006
2022-04-07 09:25:05 [task-scheduling-8] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:25:05.002
2022-04-07 09:25:05 [task-scheduling-3] [com.dch.biz.task.TestTask] [INFO] - 定时任务Diagnosis执行时间:2022/04/07 09:25:05.002
2022-04-07 09:25:10 [task-scheduling-4] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:25:10.014
2022-04-07 09:25:15 [task-scheduling-5] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:25:15.011
2022-04-07 09:25:20 [task-scheduling-6] [com.dch.biz.task.TestTask] [INFO] - 定时任务Diagnosis执行时间:2022/04/07 09:25:20.014
2022-04-07 09:25:20 [task-scheduling-10] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:25:20.014
2022-04-07 09:25:25 [task-scheduling-11] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:25:25.004
2022-04-07 09:25:30 [task-scheduling-2] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:25:30.014
2022-04-07 09:25:35 [task-scheduling-7] [com.dch.biz.task.TestTask] [INFO] - 定时任务Diagnosis执行时间:2022/04/07 09:25:35.002
2022-04-07 09:25:35 [task-scheduling-2] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:25:35.002
2022-04-07 09:25:40 [task-scheduling-2] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:25:40.005
2022-04-07 09:25:45 [task-scheduling-2] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:25:45.008
2022-04-07 09:25:50 [task-scheduling-8] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:25:50.003
2022-04-07 09:25:50 [task-scheduling-7] [com.dch.biz.task.TestTask] [INFO] - 定时任务Diagnosis执行时间:2022/04/07 09:25:50.003
2022-04-07 09:25:55 [task-scheduling-8] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:25:55.007
2022-04-07 09:26:00 [task-scheduling-8] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:26:00.005
2022-04-07 09:26:05 [task-scheduling-3] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:26:05.003
2022-04-07 09:26:05 [task-scheduling-7] [com.dch.biz.task.TestTask] [INFO] - 定时任务Diagnosis执行时间:2022/04/07 09:26:05.003
2022-04-07 09:26:10 [task-scheduling-3] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:26:10.016
2022-04-07 09:26:15 [task-scheduling-3] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:26:15.009
2022-04-07 09:26:20 [task-scheduling-9] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:26:20.009
2022-04-07 09:26:20 [task-scheduling-7] [com.dch.biz.task.TestTask] [INFO] - 定时任务Diagnosis执行时间:2022/04/07 09:26:20.009
2022-04-07 09:26:25 [task-scheduling-9] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:26:25.011
2022-04-07 09:26:30 [task-scheduling-9] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:26:30.007
2022-04-07 09:26:35 [task-scheduling-7] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:26:35.006
2022-04-07 09:26:35 [task-scheduling-9] [com.dch.biz.task.TestTask] [INFO] - 定时任务Diagnosis执行时间:2022/04/07 09:26:35.006
2022-04-07 09:26:40 [task-scheduling-7] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:26:40.003
2022-04-07 09:26:45 [task-scheduling-6] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:26:45.012
2022-04-07 09:26:50 [task-scheduling-9] [com.dch.biz.task.TestTask] [INFO] - 定时任务Diagnosis执行时间:2022/04/07 09:26:50.002
2022-04-07 09:26:50 [task-scheduling-1] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:26:50.002
2022-04-07 09:26:55 [task-scheduling-1] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:26:55.006
2022-04-07 09:27:00 [task-scheduling-1] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:27:00.005
2022-04-07 09:27:05 [task-scheduling-1] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:27:05.006
2022-04-07 09:27:05 [task-scheduling-16] [com.dch.biz.task.TestTask] [INFO] - 定时任务Diagnosis执行时间:2022/04/07 09:27:05.006
2022-04-07 09:27:10 [task-scheduling-1] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:27:10.015
2022-04-07 09:27:15 [task-scheduling-1] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:27:15.002
2022-04-07 09:27:20 [task-scheduling-1] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:27:20.002
2022-04-07 09:27:20 [task-scheduling-18] [com.dch.biz.task.TestTask] [INFO] - 定时任务Diagnosis执行时间:2022/04/07 09:27:20.002
2022-04-07 09:27:25 [task-scheduling-1] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:27:25.008
2022-04-07 09:27:30 [task-scheduling-1] [com.dch.biz.task.TestTask] [INFO] - 定时任务mapDrug执行时间:2022/04/07 09:27:30.007

通过log 我们可以看出,mapDrugExecutor每5秒钟会执行一次, 并没有与mapDiagnosisExecutor进行排队, 但是mapDiagnosisExecutor的多次任务之间并没有每5秒钟执行一次,而是等待上一次任务执行完再等待5s去执行。所以通过配置@Schedule + 线程池配置可以轻松实现多个任务之间异步, 但是同一任务同步执行。

你可能感兴趣的:(Springboot,springboot)