一、应用背景
通常,在Java中的方法调用采用的是同步调用,比如如果A()方法中调用了B()方法,则在A()方法调用B()方法之后,需要等待B()方法执行并返回后,A()方法才可以继续往下执行。这样容易导致一个问题,就是如果B()方法中的代码执行时间过长,则可能会导致调用A()方法的请求响应迟缓或者超时。为了解决这个问题,则可以使用Spirng框架下的注解@Async,通过异步调用的方式处理。本文主要是通过示例演示@Async在方法中的异步调用。
二、异步调用概念
方法A()调用方法B(),如果B()是一个异步方法,则A()方法在调用B()方法之后,不用等待B()方法执行反馈,则直接可以往下继续执行A()方法的其他代码。
三、异步调用注解@Async介绍
在Spring中,使用@Async标注某方法,可以使该方法变成异步方法,这些方法在被调用的时候,将会在独立的线程中进行执行,调用者不需等待该方法执行完成。但在Spring中使用@Async注解,需要使用@EnableAsync来开启异步调用。
四、演示示例
注释:本文的演示示例均基于springboot框架下进行编码。
1.Controller层:
@RestController
@EnableAsync
public class TreadController {
@Autowired
private TreadService service;
@RequestMapping("/ordManager")
public Integer getOrderId() throws InterruptedException {
System.out.println("controller开始层打印日志");
service.orderLog();
System.out.println("controller结束层打印日志");
return 3;
}
}
2.Service层:
@Service public class TreadService { @Async public void orderLog1() throws InterruptedException { try { Thread.sleep(3_000); } catch (Exception e) { } System.out.println("订单日志"); } }
代码运行结果:
如果不添加@EnableAsync注解,则会出现同步调用的现象。
代码运行结果:
五、手写@Async注解功能
原理:基于AOP+多线程的实现方式
- 编写自定义注解:@YdbAsync
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface YdbAsync { String value() default ""; }
- 编写AOP拦截功能:采用环绕通知方式
@Aspect public class AsyncAop { @Pointcut("@annotation(com.ydb.annotation.YdbAsync)") private void annotation(){} @Around("annotation()") public void aroundAspect(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("Aspect--环绕通知方法开始执行!!!"); joinPoint.proceed(); System.out.println("Aspect--环绕通知方法开结束执行!!"); } }
- 在目标方法中添加@YdbAsync,并增加线程运行
@YdbAsync public void orderLog() throws InterruptedException { Thread thread = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(3_000); } catch (Exception e) { } System.out.println("订单日志"); } }); thread.start(); }
- 修改contoller层调用方法
@RestController //@EnableAsync public class TreadController { @Autowired private TreadService service; @RequestMapping("/ordManager") public Integer getOrderId() throws InterruptedException { System.out.println("controller开始层打印日志"); service.orderLog(); System.out.println("controller结束层打印日志"); return 3; } }
注释:手写异步调用注解不需要添加@EnableAsync注解
代码运行结果: