默认情况下,SpringBoot下所有的定时任务都是用同一个线程池中同一个线程去执行的,即单线程执行。
从ScheduledAnnotationBeanPostProcessor类开始。ScheduledTaskRegistrar(定时任务注册类)中的ScheduleTasks中又这样一段判断:

if (this.taskScheduler == null) {
	this.localExecutor = Executors.newSingleThreadScheduledExecutor();
	this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
}

这就说明如果taskScheduler为空,那么就给定时任务做了一个单线程的线程池,正好在这个类中还有一个设置taskScheduler的方法:

public void setScheduler(Object scheduler) {
	Assert.notNull(scheduler, "Scheduler object must not be null");
	if (scheduler instanceof TaskScheduler) {
		this.taskScheduler = (TaskScheduler) scheduler;
	}
	else if (scheduler instanceof ScheduledExecutorService) {
		this.taskScheduler = new ConcurrentTaskScheduler(((ScheduledExecutorService) scheduler));
	}
	else {
		throw new IllegalArgumentException("Unsupported scheduler type: " + scheduler.getClass());
	}
}

这样问题就很简单了,只需用调用这个方法显式的设置一个ScheduledExecutorService就可以达到并发的效果了。要做的仅仅是实现SchedulingConfigurer接口,重写configureTasks方法就OK了;

package com.autoai.car.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

/**
 * Created by IntelliJ IDEA 2019.
 * User: shingmoyeung.
 * Date: 2019/11/21.
 * Time: 14:29.
 * To change this template use File Or Preferences | Settings | Editor | File and Code Templates.
 * File Description: 线程池配置
 */
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
    /**
     * 线程池名称前缀
     */
    @Value(value = "${schedule.threadname.prefix:car-schedule-pool-}")
    private String threadNamePrefix;
    /**
     * 线程池大小
     */
    @Value(value = "${schedule.poolsize:10}")
    private int poolSize;
    /**
     * 所有的定时任务都放在一个线程池中,定时任务启动时使用不同线程
     *
     * @param scheduledTaskRegistrar {@link ScheduledTaskRegistrar} 对象
     */
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        //初始化线程池
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.setPoolSize(poolSize);
        threadPoolTaskScheduler.setThreadNamePrefix("");
        threadPoolTaskScheduler.afterPropertiesSet();
        //设置线程池
        scheduledTaskRegistrar.setScheduler(threadPoolTaskScheduler);
    }
}

或者,注入以下bean

    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10);
        return scheduler;
    }

参考以下文章:

版权声明:本文为CSDN博主「指尖de柔情」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013456370/article/details/79411952