Springboot定时任务【多线程处理】

对于服务端同时开启多个定时任务的需求,按照普通的操作方式,springboot单线程的处理方式会造成许多问题,比如两个定时任务时间冲突,只能等一个执行完成在执行另一个;当一个定时任务出现问题,另一个定时任务也无法执行,整个定时任务服务可能会卡死,不再运行。下面所写,通过多线程方式调用定时任务,创建线程池,即可避免任务冲突的情况;

第一步,创建线程池

package com.**.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @ProjectName: tshare_blsj_server
 * @Package: com.**.config
 * @ClassName: TaskPoolConfig
 * @author: 
 * @description: 线程池配置
 * @date: 
 * @version: 1.0
 */
@EnableAsync
@Configuration
public class TaskPoolConfig {
    @Bean("tbsjTaskExecutor")
    public Executor mailNumPoolSingleTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //设置为1,任务顺序执行
        executor.setCorePoolSize(10);//核心线程数:线程池创建时候初始化的线程数
        executor.setMaxPoolSize(100);//最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
        executor.setQueueCapacity(20);//缓冲队列200:缓冲执行任务的队列
        executor.setKeepAliveSeconds(60);//允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
        executor.setThreadNamePrefix("tbsjTaskExecutor-");//线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());// 线程池对拒绝任务的处理策略
        return executor;
    }

    @Bean("otherSingleTaskExecutor")
    public Executor otherSingleTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //设置为1,任务顺序执行
        executor.setCorePoolSize(1);//核心线程数:线程池创建时候初始化的线程数
        executor.setMaxPoolSize(1);//最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
        executor.setQueueCapacity(20);//缓冲队列200:缓冲执行任务的队列
        executor.setKeepAliveSeconds(60);//允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
        executor.setThreadNamePrefix("otherSingleTaskExecutor-");//线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());// 线程池对拒绝任务的处理策略
        return executor;
    }
}

第二步:定时任务加注解

package com.**.task;

import com.**.service.StationInfoService;
import com.**.service.TshareStationData2Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

/**
 * @ProjectName: tshare_blsj_server
 * @Package: com.**.task
 * @ClassName: Data2NowExceptionTask
 * @author: 
 * @description:
 * @date: 
 * @version: 1.0
 */

@Slf4j
@Configuration      //1.主要用于标记配置类,兼备Component的效果。
@EnableScheduling   // 2.开启定时任务
@EnableAsync
public class Data2NowExceptionTask {

    @Autowired
    private StationInfoService stationInfoService;

    @Autowired
    private TshareStationData2Service tshareStationData2Service;


    @Scheduled(cron = "0/10 * * * * *")
    @Async("tbsjTaskExecutor")    // 通过注解指定使用的线程池
    public void det(){
        log.info("Scheduled task is running... ...");

    }
}

控制台打印,定时任务执行,可以看到,每次都是不同线程:

Springboot定时任务【多线程处理】_第1张图片

 当核心线程(10个)都用完之后,第一个线程所在的定时任务已经执行完成,那么,下一个定时任务将继续使用核心线程池中的第一个线程!

当核心线程(10个)都用完之后,第一个线程所在的定时任务尚未执行完成,将开启新的线程去执行定时任务,直到前面有任务执行完成,下个任务才会使用之前的线程去执行; 

Springboot定时任务【多线程处理】_第2张图片

你可能感兴趣的:(JAVA,java,cron,spring,boot)