spring boot @Async 的异步调用,涉及CountDownLatch堵塞和Future的超时处理

转载于:https://www.jianshu.com/p/712c60c43456

最近项目的一个业务场景需要使用异步 , 码代码到断断续续完善代码 . 查询了挺多的资料文档, 现在记录一下.

一 : 业务场景 

        类似QQ 中的设置页面 , 左侧每个选项对应右侧的具体设置 , 项目中暂且简化为需要插入7条数据到不同数据表, 第一条数据和最后一条数据是为了提醒用户开始和结束 。 其中主方法是插入1 ,立刻给用户返回数据(2-6的数据插入费时间,如果都等到插入成功再去返回给用户体验不好), 这时候我们需要开线程去分别执行2-6的插入工作,同时,7的插入必须是在2-6插入之后才可以运行.(2-6是随机的,可能全插入,可能全部不插) 。 做的结果是 : 第一条数据插入数据表,然后就直接返回用户,执行成功,中间2-6的执行过程异步执行,然后第7条数据在异步结束之后插入

12570653-d7fc101a77e1085e.png

页面类型举例

二 : 参数 

        创建一个是一个实体类来存储2-6的所有字段,添加一个标识字段来区分。存入List中 , LIst<T> 

三 : 使用技术点

        ① : spring boot 集成的异步,使用@Async来开启异步,模块启动类添加@EnableAsync 注解

                  实质上是开启线程执行异步的类,互不干扰执行。

        ② : CountDownLatch的使用

                 上面说到,我需要异步执行2-6,返回结果之后才可以去执行7。 所以此时,我们使用到了CountDownLatch工具类来完成线程之间的堵塞。CountDownLatch是一种java.util.concurrent包下一个同步工具类,它允许一个或多个线程等待直到在其他线程中一组操作执行完成。

                 1、CountDownLatch latch =new CountDownLatch(count); //构造对象时候 需要传入参数count

            2、latch .await()  能够阻塞线程 直到调用count次latch .countDown() 方法才释放线程

            3、end.countDown() 可以在多个线程中调用  计算调用次数是所有线程调用次数的总和

                  具体代码如下 :

12570653-37efc7912cc6b5b3.png

异步调用代码展示

        ③ :异步超时处理 

                因为异步是在后台执行,该项目的异步执行还需要调用其他模块的接口(参考 :spring cloud eureka的使用),导致执行速度慢,考虑到异步可能会无限执行下去,消耗资源,我们添加异步超时的处理。

                这里使用了Future<T> 接口。    

                boolean cancel(boolean mayInterruptIfRunning); 取消正在执行的异步,取消成功返回true,取消失败返回false。参数填true既取消异步,填false既不取消异步。

                boolean isCancelled(); 任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。

                boolean isDone(); 表示任务是否已经完成,完成返回true ,反之false。

                V get()throws InterruptedException, ExecutionException; 获取异步线程的执行结果,这个方法是存在堵塞效果的,任务执行完成之后就会返回执行结果,true或false返回的数据类型预Future<T> 的T一致

                Vget(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;  设置超时时间,设置时间内异步完成则则成功,超时则返回失败,返回的数据类型预Future<T> 的T一致

                参考上图,我们使用到了取消和设置超时时间的方法    

                注意 : 在写代码的过程中,我们一开始是直接在controller上面开启异步,2-6直接在异步类中开启超时,这时候不生效。查看原因是我们在异步类中的总方法调用另外五个异步,他们实际上还是一个线程。此时我们在service中调用,主方法的异步在service层,剩下五个小的异步在异步类,此时是6个线程,调用成功。

        ④ : 异步的事务

                在Async 方法上标注@Transactional是没用的。 

                在Async 方法调用的Service上标注@Transactional 有效。

转载于:https://www.jianshu.com/p/712c60c43456

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值