1 SpringBoot2.X定時(shí)任務(wù)schedule
1.1 什么是定時(shí)任務(wù)
某個(gè)時(shí)間定時(shí)處理某個(gè)任務(wù)
1.2 使用場景
發(fā)郵件、短信等
消息提醒
訂單通知
統(tǒng)計(jì)報(bào)表系統(tǒng)
...
1.3 常?定時(shí)任務(wù)
Java?帶的java.util.Timer類配置?較麻煩,時(shí)間延后問題
Quartz框架: 配置更簡單,xml或者注解適合分布式或者?型調(diào)度作業(yè)
SpringBoot框架?帶
1.4 SpringBoot使?注解?式開啟定時(shí)任務(wù)
啟動(dòng)類?? @EnableScheduling開啟定時(shí)任務(wù)漂问,?動(dòng)掃描
@EnableScheduling
@SpringBootApplication
public class Springbootdemo2Application {
定時(shí)任務(wù)業(yè)務(wù)類 加注解 @Component被容器掃描
定時(shí)執(zhí)?的?法加上注解 @Scheduled(fixedRate=2000) 定期執(zhí)??次
/**
* 模擬定時(shí)統(tǒng)計(jì)金額
*/
@Component
public class AmountScheduleTask {
@Scheduled(fixedRate = 2000)
public void sum() {
System.out.println(LocalDateTime.now() + " 當(dāng)前交易額="+ Math.random());
}
}
2 SpringBoot常?定時(shí)任務(wù)表達(dá)式配置
cron 定時(shí)任務(wù)表達(dá)式 @Scheduled(cron="*/1 * * * * *")
fixedRate: 定時(shí)多久執(zhí)??次(上?次開始執(zhí)?時(shí)間點(diǎn)后xx秒再次執(zhí)?泞坦;)
fixedDelay: 上?次執(zhí)?結(jié)束時(shí)間點(diǎn)后xx秒再次執(zhí)?
/**
* 定時(shí)統(tǒng)計(jì)訂單,金額
*/
@Component
class VideoOrderTask {
//每2秒執(zhí)行一次
@Scheduled(fixedDelay = 4000)
//@Scheduled(fixedRate = 4000)
//@Scheduled(cron = "*/1 * * * * *")
public void sum(){
System.out.println(LocalDateTime.now() + " 當(dāng)前交易額="+ Math.random());
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3 SpringBoot2.x異步任務(wù)EnableAsync
- 異步任務(wù)使?場景:
適?于處理log叉橱、發(fā)送郵件曹锨、短信……等 - 配置方法
啟動(dòng)類??使?@EnableAsync注解開啟功能舵盈,?動(dòng)掃描
@EnableAsync
@SpringBootApplication
public class Springbootdemo2Application {
定義異步任務(wù)類并使?@Component標(biāo)記組件被容器掃描,異步?法加上@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 ");
}
}
創(chuàng)建controller接口進(jìn)行測(cè)試
@GetMapping("async")
public RetData testAsync(){
long begin = System.currentTimeMillis();
asyncTask.task1();
asyncTask.task2();
asyncTask.task3();
long end = System.currentTimeMillis();
return RetData.RetSuccess( end - begin);
}
測(cè)試結(jié)果:程序時(shí)間耗時(shí)非常少
4 使?SpringBoot2.x開發(fā)異步任務(wù)Future獲取結(jié)果
定義異步任務(wù)類需要獲取結(jié)果
注意點(diǎn):
要把異步任務(wù)封裝到類??毡咏,不能直接寫到Controller
增加Future 返回結(jié)果 AsyncResult("task執(zhí)?完成");
如果需要拿到結(jié)果驮宴,需要判斷全部的 task.isDone()
編寫任務(wù)處理類,模擬兩個(gè)任務(wù)呕缭,兩個(gè)任務(wù)都睡眠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");
}
}
編寫測(cè)試接口
@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);
}
}
測(cè)試結(jié)果:兩個(gè)任務(wù)并行堵泽,總共耗時(shí)為單任務(wù)的最長耗時(shí)時(shí)間