最近刚好使用compeletablefuture优化了项目中的代码,所以跟大家一起学习completablefuture
因为completablefuture实现了future
接口,我们先来回顾future吧
future是java5新加的一个接口,它提供了一种异步并行计算的功能。如果主线程需要执行一个很耗时的计算任务,我们就可以通过future把这个任务放到异步线程中执行。主线程继续处理其他任务,异步线程处理完成后,再通过future获取计算结果
来看个简单例子吧,假设我们有两个任务服务,一个查询用户基本信息,一个是查询用户勋章信息。如下
接下来,我们来演示下,在主线程中是如何使用future来进行异步调用的。
运行结果:
总共用时806ms
如果我们不使用future进行并行异步调用,而是在主线程串行进行的话,耗时大约为300+500+300 = 1100 ms。可以发现,future+线程池异步配合,提高了程序的执行效率。
但是future对于结果的获取,不是很友好,只能通过阻塞或者轮询的方式得到任务的结果。
future.get() 就是阻塞调用,在线程获取结果之前get方法会一直阻塞。future提供了一个isdone方法,可以在程序中轮询这个方法查询执行结果eleanor roovelt。阻塞的方式和异步编程的设计理念相违背,而轮询的方式会耗费无谓的cpu资源。因此,jdk8设计出completablefuture。completablefuture提供了一种观察者模式类似的机制,可以让任务执行完成后通知监听的一方。
我们还是基于以上future的例子,改用completablefuture 来实现
可以发现,使用completablefuture,代码简洁了很多。completablefuture的supplyasync方法,提供了异步执行的功能,线程池也不用单独创建了。实际上,它completablefuture使用了默认线程池是forkjoinpool.commonpool。
completablefuture提供了几十种方法,辅助我们的异步任务场景。这些方法包括创建异步任务、任务异步回调、多个任务组合处理等方面。我们一起来学习吧
completablefuture创建异步任务,一般有supplyasync和runasync两个方法
创建异步任务
supplyasync执行completablefuture任务,支持返回值runasync执行completablefuture任务,没有返回值。实例代码如下:
completablefuture的thenrun方法,通文科大学有哪些俗点讲就是,做完第一个任务后,再做第二个任务。某个任务执行完成后,执行回调方法;但是前后两个任务没有参数传递,第二个任务也没有返回值
thenrun 和 thenrunasync 有什么区别呢?可以看下源码哈:
如果你执行第一个任务的时候,传入了一个自定义线程池:
调用thenrun方法执行第二个任务时,则第二个任务和第一个任务是共用同一个线程池。调用thenrunasync方法执行第二个任务时,则第一个任务使用的是你自己传入的线程池,第二个任务使用的是forkjoin线程池tips:后面介绍的thenaccept和thenacceptasync,thenapply和thenapplyasync等,它们之间的区别也是这个哈。
completablefuture的thenaccept方法表示,第一个任务执行完成后,执行第二个回调方法任务,会将第一个任务的执行结果,作为第二个任务的入参,传递到回调方法中,但是回调方法是没有返回值的。
completablefuture的thenapply方法表示,第一个任务执行完成后,执行第二个回调方法任务,会将第一个任务的执行结果,作为第二个任务的入参,传递到回调方法中,并且回调方法是有返回值的。
completablefuture的exceptionally方法表示,某个任务执行异常时,执行的回调方法;并且有抛出异常作为参数,传递到回调方法。
completablefuture的whencomplete方法表示,某个任务执行完成后,执行的回调方法,无返回值;并且whencomplete方法返回的completablefuture的result是上个任务的结果。
completablefuture的handle方法表示,某个任务执行完成后,执行回调方法,并且是有返回值的;并且handle方法返回的completablefuture的result是回调方法执行的结果。
thencombine / thenacceptboth / runafterboth都表示:将两个completablefuture组合起来,只有这两个都正常执行完了,才会执行某个任务。
区别在于:
thencombine:会将两个任务的执行结果作为方法入参,传递到指定方法中,且户外拓展小游戏有返回值thenacceptboth: 会将两个任务的执行结果作为方法入参,传递到指定方法中,且无返回值runafterboth:不会把执行结果当做方法入参,且没有返回值。applytoeither / accepteither / runaftereither 都表示:将两个completablefuture组合起来,只要其中一个执行完了,就会执行某个任务。
所有任务都执行完成后,才执行 allof 返回的completablefuture。如果任意一个任务异常,allof的completablefuture,执行get方法,会抛出异常
anyof
任意一个任务执行完,就执行anyof返回的completablefuture。如果执行的任务异常,anyof的completablefuture,执行get方法,会抛出异常
thencompo方法会在某个任务执行完成后,将该任务的执行结果,作为方法入参,去执行指定的方法。该方法会返回一个新的completablefu初中学习ture实例
如果该completablefuture实例的result不为null,则返回一个基于该result新的completablefuture实例;如果该completablefuture实例为null,然后就执行这个新任务completablefuture 使我们的异步编程更加便利的、代码更加优雅的同时,我们也要关注下它,使用的一些注意点。
future需要获取返回值,才能获取到异常信息。如果不加 get()/join()方法,看不到异常信息。小伙伴们使用的时候,注意一下哈,考虑是否加try…catch…或者使用exceptionally方法。
completablefuture的get()方法是阻塞的,如果使用它来获取异步调用的返回值,需要添加超时时间~
completablefuture代码中又使用了默认的线程池,处理的线程个数是电脑cpu核数-1。在大量请求过来的时候,处理逻辑复杂的话,响应会很慢。一般建议使用自定义线程池,优化线程池配置参数。
completablefuture的get()方法是阻塞的,我们一般建议使用future.get(3, timeunit.conds)
。并且一般建议使用自定义线程池。
但是如果线程池拒绝策略是discardpolicy
或者discardoldestpolicy
,当线程池饱和时,会直接丢弃任务,不会抛弃异常。因此建议,completablefuture线程池策略最好使用abortpolicy,然后耗时的异步线程,做好线程池隔离哈。
到此这篇关于java8的异步编程利器completablefuture详解的文章就介绍到这了,更多相关java8completablefuture异步编程内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!
本文发布于:2023-04-06 02:59:52,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/fba51b1b588320c577a427a2179d642a.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:Java 8 的异步编程利器 CompletableFuture的实例详解.doc
本文 PDF 下载地址:Java 8 的异步编程利器 CompletableFuture的实例详解.pdf
留言与评论(共有 0 条评论) |