异步编程
一、异步编程的理解
参考文档:https://blog.51cto.com/stevex/1284437
二、实现步骤
1、开启异步编程支持
在启动类加上下面注解,表示整个项目都可使用,也可以在单独的类上面加,表示只有该类支持
@EnableAsync
2、在service层编写业务时,方法上加 @Async注解
package com.hm.sringboot.service;
import com.hm.sringboot.pojo.User1;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
* @ClassName
* @Description TODO
* @Author ZQS
* @Date 2020/9/5 0005 16:27
* @Version 1.0
**/
@Slf4j
@Component
public class AsyncDemo {
/**
* 没有返回值的异步任务:例如发送短信邮箱
*/
@Async
public void asyncNoResult() throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
log.info("没有返回值的线程名称为:{}",Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(2);
}
/**
* 有返回值的 :例如文件上传 需要拿到文件存储的位置/id
*/
@Async
public Future<User1> asyncResult ()throws InterruptedException{
TimeUnit.SECONDS.sleep(2);
log.info("有返回值的线程名称为:{}",Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(2);
User1 user1=new User1(1,"小白","rap");
return new AsyncResult<>(user1);
}
}
3、编写控制层
package com.hm.sringboot.controller;
import com.hm.sringboot.pojo.User1;
import com.hm.sringboot.service.AsyncDemo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* @ClassName
* @Description TODO
* @Author ZQS
* @Date 2020/9/5 0005 16:44
* @Version 1.0
**/
@RestController
@RequestMapping("/")
@Slf4j
public class AsyncController {
@Autowired
AsyncDemo asyncDemo;
@GetMapping("async1")
public String async1() throws ExecutionException, InterruptedException {
asyncDemo.asyncNoResult();
return "方法调用成功";
}
@GetMapping("async2")
public String async2() throws InterruptedException, ExecutionException {
Future<User1> stringFuture = asyncDemo.asyncResult();
User1 user1 = stringFuture.get();
log.info("调用有返回值的异步方法" + "成功");
return "成功";
}
}
4、注意点(有返回值和无返回值)
A:当调用无返回值时候,访问页面直接返回
B:当调用有返回值时候,访问页面会等待2秒执行(TimeUnit.SECONDS.sleep(2))
原因:
1、因为控制层要拿到service层的的结果(主线程要拿到service线程的结果),才能返回给前台数据,而service层又执行睡眠方法
2、当控制层不需要拿到service的结果时,并不需要等待
所以等待原因是控制层需要拿到service层的数据