Supplier 惰性调用和 Future#get 同步等待调用结合

本文介绍了如何在Java中使用CompletableFuture进行异步任务处理,但遇到主线程阻塞问题。作者通过引入Supplier接口实现惰性求值,使得异步结果在需要时才获取,避免了阻塞。最后,作者还展示了如何通过AsyncResp包装Future和CompletableFuture,以提升代码的可读性和业务语义一致性。
摘要由CSDN通过智能技术生成

📖一、背景介绍

关于任务异步执行,两个点不可避免:异步结果和异步回调。

而在我的工程中有这样一段代码:使用 CompletableFuture 进行封装,可以异步执行,异步回调,通过 get() 等待异步任务的结果

注:任何方法都可以封装成 CallbackTask 调用。

图片

但用着用着就发现明显的不对劲,主线程会阻塞等待结果。异步转同步!

图片

Optional.ofNullable(invoke.get(DEFAULT_MAX_TIMEOUT, TimeUnit.SECONDS))。get() 方法会进行阻塞等待。invokeWithResult 封装得不是很理想。

图片

有没有好的方法,不执行阻塞等待呢?直接返回 CompletableFuture 就可以了,等主线程用到的时候,再调用 CompletableFuture#get获取。

但用 CompletableFuture 作为方法返回值,个人觉得语义并不很好,有没有其他方式呢,带着这个问题过了一天,终于有了灵感 -- supplier 惰性求值。

📒二、supplier 惰性

Supplier接口在 Java 中通常被用于实现惰性求值。Supplier的特点在于它的 get()方法,该方法没有输入参数,并在被调用时返回一个T类型的值。在Supplier 被定义时,并不会执行 get() 方法中的代码;只有在显式调用 get() 方法时,代码才会执行,并且生成并提供一个值。

图片

这允许代码在需要时才生成值,从而实现了惰性求值。因为Supplier推迟了执行,直到调用者准备好接收值,这可以提高性能,避免不必要的计算,尤其是在处理耗时的操作或创建资源密集型对象时。

一个简单的例子可以展示Supplier的惰性行为

图片

灵感来了,尝试用 supplier 来解决上面的问题。

📑三、supplier 和 Future#get 结合

将 Future#get 用 supplier 表达,等需要异步结果的时候再从 supplier 中获取。

图片

没错,supplier 达到效果。主线程使用 invokeWithSupplier 时不再堵塞。只是有 supplier#get才会阻塞获得结果值。

但为了更符合业务语义,进一步将 supplier 进行包装,用包装类承载结果

图片

用 AsyncResp 作为返回类型,最终方法如下:

图片

后来回顾,AsyncResp 甚至可以对 CompletableFuture 进行包装,如下所示:

图片

真的是,条条道路通罗马,多一些思考发现代码其实还挺有趣的!

异步、异步回调、异步结果是非常常见的问题,应用的场景也特别多,工程中常备此类工具。

对于 supplier 惰性能力,包装了 Future#get,觉得挺有意思的,决定把过程记录下来。

最后说一句(求关注!)

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!

  • 22
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值