前言:
这次介绍一下Spring中如何进行异步编程以及事件驱动编程。
前几天看了一些博客,大体是讲Spring与众多开源项目都在进行异步驱动思想的推广,希望能够在javaee、移动端等领域中大量普及这种开发方式。
那么什么是异步与事件驱动编程呢?
异步:
顾名思义是为了区分同步而存在的概念,那么它的核心就是可以有副线去开启任务,不必在主线上阻塞排队执行。
关于异步,还有并行与并发的概念
并行:多cpu能够同时运行
并发:更多的是指cpu切换时间片
还有一些概念就是说,多线程不一定是只有在多c机器上才有意义,如果只有一个cpu,那么多线程的意义在于避免了阻塞,比如你的io线程在阻塞,这个时候还可以切换cpu资源去执行别的任务。
事件驱动:
事件驱动是一种很宽泛的说法了,领域驱动编程中的DDD+CQRS、设计模式中的观察者模式、eventbus、rxjava、spring event、nodejs等诸多编程方式都可以说是一种事件驱动的思想。
那么它解决的问题是什么呢?
首先是解耦,不再需要显示的调用各种service,我只需要发出通知,至于谁去执行这个任务,是背后消费者的逻辑了,程序只需要关心强一致相关流程上的事情,至于其他可以背后处理的事情,都可以背后去处理。
其次是提高了效率,针对异步型的驱动,主线程可以更快的返回用户端,那么吞吐量和性能自然有提升。另外,也可以配合MQ做一些流量削峰的效果。当然MQ本质上也是事件驱动的概念。
以上两个概念通常都是相辅相成的,应用场景很广泛,像操作系统里面的很多处理都是基于异步事件驱动,还有Linux IO模型中的nio、aio、epoll、poll、select等处理,还有应用端把传统的rpc同步查询搭建成读写分离系统,都是基于这种编程思想去实现的。
今天主要来介绍一下Spring中提供的@Async注解以及事件驱动接入方式
@Async使用方式
在Spring中使用异步编程的方式非常简单,首先在Spring配置中开启异步功能
配置方式是加上@EnableAsync注解

然后,我们就可以使用这种注解进行异步处理了

如上图,saveUser这个方法原本是需要同步处理的,那么只需要在方法上打上@Async注解便可以将它变成异步处理。@Async这个注解可以指定具体的线程池,也可以使用默认的线程池,上图是博主自己配置了专属的线程池,配置代码如下:

如果使用默认的线程池,也可以通过application.properties配置文件更改线程池的参数

上述是void类型的异步处理,如果方法是有返回值的需要如何处理呢?

如上图,如果是有返回值的方法,那么在@Async注解打上的时候,就可以将返回值设置成为Future对象,并且将最后的return结果包装成为AsyncResult对象,这样就可以拿到Spring异步处理的Future对象,再对Future对象进行get或者join操作即可拿到处理的结果,这里需要注意的是在阻塞等待执行结果的处理上,不要忘了异常处理。
@Async异常处理
异常处理分两种,void类型方法的异常处理如下:


如上图,首先定义一个专属的异常处理handler,然后将handler接入AsyncConfig。
这样,异步处理的异常就会进到Handler方法中,可以根据method、参数等信息进行专门的处理,也可以接入事件驱动等进行分发处理。
有返回值的@Async可以直接在方法中进行throw处理,最终异常会进入get阻塞catch块中,注意把异常信息往上抛即可,也可以在子线程中try catch处理,这个看具体需求了,不要忘了打日志,还有在分布式链路中不要忘了把父子线程traceid串起来,当然这块基本上大厂的框架会封装,像携程、大众点评的cat,阿里的鹰眼等。
事件驱动
博主之前有篇博客说到过事件驱动,当时只是作为spring生命周期中的一环进行介绍的。
今天来讲一下,如果我们想借助Spring的事件驱动做内存mq,就类似于EventBus、Rxjava的功能,我们可以怎么做。
首先来定义一个Event

然后我们针对Event来进行通知,封装一个notify类

然后我们针对Event来消费
一共有两种方式去消费:
1.@EventListener
2.ApplicationListener<ApplicationEvent>


如上图,打上@Async注解的消费就是异步的,如果去掉@Async注解,消费就变成同步的,主线程会等待消费处理结束才能返回。
来看一下例子:
同步方式:




异步方式:
就是把@Async注解加上了

如上图,可以对比看到,主线程没有再等待事件消费方的执行了,直接先打印了日志。
总结:
今天介绍了Spring的事件驱动异步处理方式,主要还是介绍一种思想,这种思想可以在很多项目中运用,去提高项目的性能、吞吐量。改良项目的架构、改良项目的分层、提高开发人员工作效率等
网友评论