天天看点

springboot多线程定时任务的使用

对于服务端的多线程定时任务,需要怎么使用呢,其实很简单,仅需两步(创建线程池+开启定时任务),快来看看吧

1.首先第一步,创建好定时任务线程池(这里创建了两个,可根据业务需求进行扩展):

package com.digitalgd.goff.service.task;

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;

/**
 * @author yangli
 * @ClassName ThreadPoolConfig
 * @Description 线程池配置
 * @date 2020/7/10 16:13
 **/
@EnableAsync
@Configuration
public class TaskPoolConfig {
    @Bean("mailNumPoolSingleTaskExecutor")
    public Executor mailNumPoolSingleTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //设置为1,任务顺序执行
        executor.setCorePoolSize(1);//核心线程数:线程池创建时候初始化的线程数
        executor.setMaxPoolSize(1);//最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
        executor.setQueueCapacity(20);//缓冲队列200:缓冲执行任务的队列
        executor.setKeepAliveSeconds(60);//允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
        executor.setThreadNamePrefix("mailNumPoolSingleTaskExecutor-");//线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
        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;
    }
}
           

2.创建好线程池后,就可以正式开始定时任务使用了:

package com.digitalgd.goff.service.task;


import com.digitalgd.goff.service.ServiceMonitoringService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;

/**
 * @author yangli
 * @ClassName ServiceMonitorTask
 * @Description 定时任务
 * @date 2020/7/10 16:13
 **/
@Component
@Slf4j
@EnableScheduling
@EnableAsync
public class ServiceMonitorTask {

    @Scheduled(cron = "0 0 8,16 * * ?")  // 标明此方法为定时任务
    @Async("otherSingleTaskExecutor")    // 通过注解指定使用的线程池
    public void serviceUseCountTask(){
        log.info("服务被调用情况start");
        try {
            log.info("服务被调用情况end");
        } catch (Exception e) {
            log.info("服务调用error");
        }
    }

    @Scheduled(cron = "0 30 8,16 * * ?")
    @Async("otherSingleTaskExecutor")
    public void healthStatusTask(){
        log.info("服务统计start");
        try {
            log.info("服务统计end");
        } catch (Exception e) {
            log.info("服务统计error");
        }
    }

    @Scheduled(cron = "0 0 0,12 * * ?")
    @Async("otherSingleTaskExecutor")
    public void requestCountTask(){
        log.info("服务请求数---------");
    }
}
           

关于注解:

@Async是spring为了方便开发人员进行异步调用的出现的,在方法上加入这个注解,spring会从线程池中获取一个新的线程来执行方法,实现异步调用

@EnableAsync表示开启对异步任务的支持,可以放在springboot的启动类上,也可以放在自定义线程池的配置类上

@EnableScheduling:开启对定时任务的支持,在相应的方法上添加@Scheduled声明需要执行的定时任务。

@Scheduled(cron = “0 0 8,16 * * ?”) , 标明此方法为需要执行的定时任务,cron表达式由6到7个时间元素组成,每个字符表示一个时间含义,从左到右(用空格隔开),依次表示为:

秒 分 小时 月份中的日期 月份 星期 年份

四.注解没生效的原因

1.异步方法使用static修饰

2.异步方法类没有使用@Service注解(或其他注解)导致spring无法扫描到异步类

3.controller中需要使用@Autowired或@Resource等注解自动注入service类,不能自己手动new对象

到此为止定时任务的配置就已经全部结束,快来愉快的使用吧!