目录

      • 定时任务Schedule
      • 异步任务Async
      • cron表达式

 

spring自带了定时任务、异步任务,springboot中自然也包含了进来,此处主要介绍在springboot中的使用。

定时任务、异步任务是spring|spring自带的,不需要额外添加依赖。

 

定时任务Schedule

1、引导类上加 @EnableScheduling
 

2、yml中配置定时任务的线程池

spring:
  task:
    scheduling:
      pool:
        #定时任务线程池中的线程数,默认值1
        size: 10

一个线程执行一个定时任务,如果线程数不够,会出现部分定时任务没有可用线程来执行的情况。

springboot的定时任务、异步任务都是使用单独的线程池,如果公司有线程池使用规范或觉得内置的线程池不满足需求,可以使用自定义的线程池。

 

3、编写定时任务

通常会把定时|异步任务抽出来,统一放在单独的包、类中,方便维护

@Component  //放到容器中
public class XxxTask {

    @Scheduled(fixedRate = 5000)  //指定执行时间。每5000ms执行1次,间隔是距上次执行开始
    public void task1(){
		//要执行的代码
    }

    @Scheduled(fixedDelay = 5000) //每5000ms执行1次,间隔是距上次执行结束
    public void task2(){
		//要执行的代码
    }

	@Scheduled(fixedRateString = "5000")  //fixedRateString、fixedDelayString 分别对应以上2种,只是把值写成字符串形式
    public void task3(){
		//要执行的代码
    }

	@Scheduled(cron = "0 0/10 * * * ?")  //使用cron表达式指定
    public void task4(){
		//要执行的代码
    }
    
}

 

异步任务Async

异步任务可分为2类

  • 不需要返回数据:比如处理日志、发送邮件、短信…
  • 需要返回数据:比如用户支付订单要校验库存、用户余额、风控…都没有问题才允许支付订单

异步任务都是启动一条新线程来执行,不阻塞当前线程,可以提高效率。
 

1、引导类上加 @EnableAsync
 

2、yml中配置异步任务的线程池

spring:
  task:
    execution:
      #线程名称前缀,默认task-
      thread-name-prefix: async-task-thread-
      #异步线程池配置
      pool:
        #默认值 8
        core-size: 6
        #默认值 Integer.MAX_VALUE
        max-size: 20
        #异步任务队列的容量,默认值 Integer.MAX_VALUE
        queue-capacity: 300

 

3、编写异步任务

一个异步任务对应一个方法,所以又叫做异步方法

@Component  //放到容器中
@Async  //将类中的方法都标识为异步方法。如果不需要标注全部方法,可以标在方法上
public class XxxAsyncTask {

    //不需要返回结果的
    public void task1(){
        //......
    }

    //需要返回结果的,泛型指定要返回的数据类型
    public Future<String> task2(){
        //......
        //参数是要返回的数据
        return new AsyncResult<>("success");
    }

    public Future<String> task3(){
        //......
        return new AsyncResult<>("fail");
    }

}

注意点

  • 异步任务会作为 Future 提交给线程池执行,所以异步任务的返回值只能是 void 或 Future
  • 异步任务不能使用 private 或 static 修饰,不然在线程池中调用不了
  • 异步任务不能与调用方在同一个类中,通常是把异步任务写在单独的包、类中,方便维护

 

4、使用异步任务

@Service
public class XxxService {

    @Autowired
    private XxxAsyncTask xxxAsyncTask;

    public void xxx() {
        //......

        //都是启动新线程来执行task
        xxxAsyncTask.task1();
        Future<String> task2 = xxxAsyncTask.task2();
        Future<String> task3 = xxxAsyncTask.task3();

        //......   //当前线程继续往下执行

        //当前线程需要使用异步任务的返回结果时,使用get()阻塞当前线程等待异步任务执行完毕
        try {
        	//能指定超时时间的方法都尽量指定超时时间,避免发生异常时一直阻塞线程
            String r2 = task2.get(1, TimeUnit.MINUTES);
            String r3 = task3.get(1, TimeUnit.MINUTES);
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }

        //......  //当前线程继续往下执行
    }

}

 

cron表达式

一共7个字段,依次是

  • second:0-59
  • minute:0-59
  • hour:0-23
  • day of month:1-31
  • month:1-12
  • day of week:1-7
  • year:1970-2099

前6个必填,第7个选填、可以缺省。
 

使用示例

# ?表示不关心该字段的值,用于第六个(day of week)字段
# 一般前面写0,后面写*,*表示任意值


#直接写数字表示在指定时间执行。如果年月日时分秒都写死,则只在指定时间执行一次
0 0 10 * * ?   # 每天10点执行1次
0 0 0 1 * ?  #每月1号凌晨执行1次


# */n 表示每隔n执行1次,也可以写成0/n
0 0 */2 * * ?  #每隔2小时执行1次


# -表示区间
0 0 10-14 * * ?   # 每天的10、11、12、13、14点各执行1次


# ,表示或者
0 0 9,15,21 * * ?  #每天9点、15点、21点各执行1次

更多推荐

SpringBoot 定时任务Schedule,异步任务Async