1 SpringBoot2.X定时任务schedule
1.1 什么是定时任务
某个时间定时处理某个任务
1.2 使用场景
发邮件、短信等
消息提醒
订单通知
统计报表系统
...
1.3 常⻅定时任务
Java⾃带的java.util.Timer类配置⽐较麻烦,时间延后问题
Quartz框架: 配置更简单,xml或者注解适合分布式或者⼤型调度作业
SpringBoot框架⾃带
1.4 SpringBoot使⽤注解⽅式开启定时任务
启动类⾥⾯ @EnableScheduling开启定时任务,⾃动扫描
@EnableScheduling
@SpringBootApplication
public class Springbootdemo2Application {
定时任务业务类 加注解 @Component被容器扫描
定时执⾏的⽅法加上注解 @Scheduled(fixedRate=2000) 定期执⾏⼀次
/**
* 模拟定时统计金额
*/
@Component
public class AmountScheduleTask {
@Scheduled(fixedRate = 2000)
public void sum() {
System.out.println(LocalDateTime.now() + " 当前交易额="+ Math.random());
}
}
2 SpringBoot常⽤定时任务表达式配置
cron 定时任务表达式 @Scheduled(cron="*/1 * * * * *")
fixedRate: 定时多久执⾏⼀次(上⼀次开始执⾏时间点后xx秒再次执⾏;)
fixedDelay: 上⼀次执⾏结束时间点后xx秒再次执⾏
/**
* 定时统计订单,金额
*/
@Component
class VideoOrderTask {
//每2秒执行一次
@Scheduled(fixedDelay = 4000)
//@Scheduled(fixedRate = 4000)
//@Scheduled(cron = "*/1 * * * * *")
public void sum(){
System.out.println(LocalDateTime.now() + " 当前交易额="+ Math.random());
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3 SpringBoot2.x异步任务EnableAsync
- 异步任务使⽤场景:
适⽤于处理log、发送邮件、短信……等 - 配置方法
启动类⾥⾯使⽤@EnableAsync注解开启功能,⾃动扫描
@EnableAsync
@SpringBootApplication
public class Springbootdemo2Application {
定义异步任务类并使⽤@Component标记组件被容器扫描,异步⽅法加上@Async
package com.jackyan.springbootdemo2.task;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class AsyncTask {
@Async
public void task1(){
try {
Thread.sleep(4000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" task 1 ");
}
@Async
public void task2(){
try {
Thread.sleep(4000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" task 2 ");
}
@Async
public void task3(){
try {
Thread.sleep(4000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" task 3 ");
}
}
创建controller接口进行测试
@GetMapping("async")
public RetData testAsync(){
long begin = System.currentTimeMillis();
asyncTask.task1();
asyncTask.task2();
asyncTask.task3();
long end = System.currentTimeMillis();
return RetData.RetSuccess( end - begin);
}
测试结果:程序时间耗时非常少
4 使⽤SpringBoot2.x开发异步任务Future获取结果
定义异步任务类需要获取结果
注意点:
要把异步任务封装到类⾥⾯,不能直接写到Controller
增加Future 返回结果 AsyncResult("task执⾏完成");
如果需要拿到结果,需要判断全部的 task.isDone()
编写任务处理类,模拟两个任务,两个任务都睡眠4000毫秒
@Component
public class AsyncTask {
@Async
public Future<String> task4(){
try {
Thread.sleep(4000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" task 4 ");
return new AsyncResult<String>("task4");
}
@Async
public Future<String> task5(){
try {
Thread.sleep(4000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" task 5 ");
return new AsyncResult<String>("task5");
}
}
编写测试接口
@RestController
@RequestMapping("/app/v1/pub/test")
public class TestController {
@Autowired
private AsyncTask asyncTask;
@GetMapping("async")
public RetData testAsync(){
long begin = System.currentTimeMillis();
Future<String> task4 = asyncTask.task4();
Future<String> task5 = asyncTask.task5();
for(;;){
if(task4.isDone() && task5.isDone()){
try {
String task4Result = task4.get();
System.out.println(task4Result);
String task5Result = task5.get();
System.out.println(task5Result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}finally {
break;
}
}
}
long end = System.currentTimeMillis();
return RetData.RetSuccess( end - begin);
}
}
测试结果:两个任务并行,总共耗时为单任务的最长耗时时间