异步任务根据处理方式的不同可以分为无返回值异步调用和有返回值异步调用。
开启异步任务和定时任务
package com.codel.async;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableAsync //开启异步
@EnableScheduling //启用定时调度
public class AsyncApplication {
public static void main(String[] args) {
SpringApplication.run(AsyncApplication.class, args);
}
}
异步任务
1.异步service类
package com.codel.async.service;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
/**
* 我的异步服务
*
* @author codel
* @date 2021/09/23
*/
@Service
public class MyAsyncService {
/**
* 无返回值的异步调用
* @throws InterruptedException
*/
@Async//表明该方法是一个异步方法
public void sendMSM() throws InterruptedException {
System.out.println("调用短信方法....");
long startTime = System.currentTimeMillis();
Thread.sleep(5000);
long endTime = System.currentTimeMillis();
System.out.println("短信方法完成,耗时:"+(endTime-startTime));
}
/**
* 发送msm2
*
* @return {@link CompletableFuture}<{@link Integer}>
* @throws InterruptedException 中断异常
*/
@Async//表明该方法是一个异步方法
public CompletableFuture<Integer> sendMSM2() throws InterruptedException {
System.out.println("调用短信方法2....");
long startTime = System.currentTimeMillis();
Thread.sleep(5000);
int interval=235432;
long endTime = System.currentTimeMillis();
System.out.println("短信方法完成2,耗时:"+(endTime-startTime));
return CompletableFuture.completedFuture(interval);
}
/**
* 发送msm3
*
* @return {@link CompletableFuture}<{@link Integer}>
* @throws InterruptedException 中断异常
*/
@Async//表明该方法是一个异步方法
public CompletableFuture<Integer> sendMSM3() throws InterruptedException {
System.out.println("调用短信方法3....");
long startTime = System.currentTimeMillis();
Thread.sleep(3000);
int interval=234232;
long endTime = System.currentTimeMillis();
System.out.println("短信方法完成3,耗时:"+(endTime-startTime));
return CompletableFuture.completedFuture(interval);
}
}
这个service类里面有 无返回值异步调用 和 有返回值异步调用。
用 @Async表明该方法是一个异步方法。
关于CompletableFuture,是因为异步,所以返回类型只能是void和CompletableFuture类型的。
2.controller类
package com.codel.async.controller;
import com.codel.async.service.MyAsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
/**
* 我的异步控制器
*
* @author codel
* @date 2021/09/23
*/
@RestController
public class MyAsyncController {
@Autowired
private MyAsyncService myAsyncService;
/**
* 测试
*
* @return {@link String}
* @throws InterruptedException 中断异常
*/
@GetMapping("/sendmail")
public String test() throws InterruptedException {
long startTime = System.currentTimeMillis();
// 模拟发送邮件 因为是异步,而且没有数据返回的时候,所以主线程会先走,不会等待事务完成再走。
myAsyncService.sendMSM();
long endTime = System.currentTimeMillis();
System.out.println("主线程耗时:" + (endTime - startTime));
return "信息发送成功!";
}
/**
* test2
*
* @return {@link String}
* @throws InterruptedException 中断异常
* @throws ExecutionException 执行异常
*/
@GetMapping("/sendmail2")
public String test2() throws InterruptedException, ExecutionException {
long startTime = System.currentTimeMillis();
// 模拟发送邮件 因为是异步,而且没有数据返回的时候,所以主线程会先走,不会等待事务完成再走。
CompletableFuture<Integer> msm2 = myAsyncService.sendMSM2();
CompletableFuture<Integer> msm3 = myAsyncService.sendMSM3();
int i = msm2.get() + msm3.get();
System.out.println("异步任务数据统计汇总结果:"+i);
long endTime = System.currentTimeMillis();
System.out.println("主线程耗时2:" + (endTime - startTime));
return "信息发送成功2!";
}
}
3.执行结果:
1、调用的短信业务无回调,主流程无需等待短信业务完成,所以主流程耗时1豪秒与短信业务耗时无关。
2、数据统计方法有回调,主流程需要等待返回值才会往下执行,还有业务2和业务3的耗时是3秒、5秒,由于他们是异步执行的(sleep),所以总耗时也就5秒左右。
定时任务
1.service
package com.codel.async.service;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;
@Service
public class ScheduledTaskService {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private Integer count1 = 1;
private Integer count2 = 1;
private Integer count3 = 1;
@Scheduled(fixedRate = 60000)//一分钟执行一次
public void test1() {
System.out.printf("定时任务fixeRate第%s次执行,当前时间为:%s%n", count1++, dateFormat.format(new Date()));
}
@Scheduled(fixedDelay = 60000)//表示上一次任务执行完成之后,在指定时间后执行下一次任务
public void test2() throws InterruptedException {
System.out.println(String.format("定时任务fixeDelay第%s次执行,当前时间为:%s", count2++, dateFormat.format(new Date())));
Thread.sleep(10000);
}
@Scheduled(cron = "0 * * * * *")//定制任务触发的时间
public void test3() {
System.out.println(String.format("定时任务cron第%s次执行,当前时间为:%s", count3++, dateFormat.format(new Date())));
}
}
2.执行结果:
注解的解释:
@Scheduled(fixedRate = 6000) //每6秒执行一次 ,含执行时间
@Scheduled(fixedDelay = 6000) //间隔6秒执行一次,不含执行时
@Scheduled(cron="0 * * * * *") //每分钟定时执行