美文网首页
@Async注解&事件驱动编程方式

@Async注解&事件驱动编程方式

作者: 但时间也偷换概念 | 来源:发表于2019-03-08 18:32 被阅读0次

前言:

这次介绍一下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注解

@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

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

通知类

然后我们针对Event来消费

一共有两种方式去消费:

1.@EventListener

2.ApplicationListener<ApplicationEvent>

@EventListener方式 ApplicationListener方式

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

来看一下例子:

同步方式:

异步方式:

就是把@Async注解加上了

如上图,可以对比看到,主线程没有再等待事件消费方的执行了,直接先打印了日志。

总结:

今天介绍了Spring的事件驱动异步处理方式,主要还是介绍一种思想,这种思想可以在很多项目中运用,去提高项目的性能、吞吐量。改良项目的架构、改良项目的分层、提高开发人员工作效率等


相关文章

网友评论

      本文标题:@Async注解&事件驱动编程方式

      本文链接:https://www.haomeiwen.com/subject/jchdpqtx.html