定时任务 @Scheduled 中不能使用多线程的解决方案

由于SpringBoot使用@scheduled定时执行任务的时候是在一个单线程中,如果有多个任务,其中一个任务执行时间过长,则有可能会导致其他后续任务被阻塞直到该任务执行完成。由于每次定时任务执行时,大概有一万条左右的数据需要插入,所以就想用多线程的方式去执行。在网上找了好几种方法去执行,发现都没有在定时任务中成功启动多线程。

例如(1) @EnableAsync和@Async 注解的方法;(2)通过实现SchedulingConfigurer接口,实现configureTasks方法,给Scheduling配置多个线程。这两种方法我都没有测试成功。就想着注解调用是很简单已用,但是也依赖于每个人的配置文件是怎么写的,有时候会让人琢磨不透。

所以还是手动调用稳定呀,也没有麻烦到哪里去!!!

 1. 配置自定义的线程池

@Configuration
public class TalentIotThreadConfig  {

//获取当前机器的核数
    public static final int cpuNum = Runtime.getRuntime().availableProcessors();

    @Bean("TalentIotThread")
    public ThreadPoolTaskExecutor  getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(cpuNum);//核心线程大小
        taskExecutor.setMaxPoolSize(cpuNum * 2);//最大线程大小
        taskExecutor.setQueueCapacity(500);//队列最大容量
        //当提交的任务个数大于QueueCapacity,就需要设置该参数,但spring提供的都不太满足业务场景,可以自定义一个,也可以注意不要超过QueueCapacity即可
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        taskExecutor.setAwaitTerminationSeconds(60);
        taskExecutor.setThreadNamePrefix("ABCThread-");
        taskExecutor.initialize();
        return taskExecutor;
    }
}

2. 调用,ThreadPoolExecutor它的顶级父类是Executor接口,只包含了一个方法——execute,这个方法也就是线程池的“执行”。

 
public class IotTimer {
  //通过注解引入配置
    @Resource(name = "TalentIotThread")
    private Executor executor;
 
    @Scheduled(cron = "0 */2 * * * ?")
    void talIotDataShare() {
        for (TalIotDateShare iotDateShare : shareList) {
 
             executor.execute(() -> {
                   // 业务代码                 
 
                 });
 
           }
 
    }
 
}

如此就实现了在定时任务中使用多线程。

你可能感兴趣的:(java,开发语言)