jdk1.8 CompletableFuture尝试

来源:互联网 发布:js中new 关键字 编辑:程序博客网 时间:2024/05/18 14:28

初识Future

忘了第一次是怎么接触CompletableFuture的了,因为是间接了解到的。首先了解到的是Future接口,朋友给我个人项目搭后台架构时用到的,我看代码时发现用到了这个这东西。在这之前,对它一无所知,就比较好奇,了解到是用于异步操作的。java方法也能异步调用?我觉得很酷,开了眼界,再结合js,觉得这东西很有价值,所以那时就有一个想法在心中萌芽,就是在实际的工作项目中,去使用异步操作。但是到这里,就只知道Future这个接口,而且这个接口是jdk1.5就提供了,对CompletableFuture还是最不熟系的陌生人。

同步异步,纠缠不休

Future渐渐被遗忘了,毕竟时间精力大部分都得花在工作上,个人项目也处在起步阶段,java合理使用异步操作能提高性能,但是个人项目现阶段还没有必要花时间精力去考虑性能问题。工作上忙于应付需求和准备面试,也将java异步抛之脑后了。直到前段时间,被安排做性能优化,主要是前端。大约花了十来天,恶补浏览器运行机制、浏览器多线程模型等基础性、原理性知识,希望能从更深层次地认识浏览器的运行,进而对前端性能进行优化。过程是艰辛的,结果也是很凄凉的,到最后前端还是没有进行任何的优化,最后还是通过优化了一些sql语句,才使性能有所提升。但是整个过程下来,对浏览器的运行机制的认识还是进步了不少,对后面自己写前端代码会有不小的帮助。在这个过程中,其实优化的重点一直集中在同步和异步,想尽量将同步改为异步。不过最后发现,由于js实现异步发送Ajax请求如此的简单,以至于没有找到提升的空间。前端优化无疾而终。

CompletableFuture第一次亲密接触

寄予厚望的前端优化以失败而告终,只有转向后台了。从这时起,才开始真正尝试在后台使用异步。一通百度java异步调用方法,决定学习和使用jdk1.8新增的CompletableFuture类来实现异步操作。后台的业务场景是这样的:这是个医疗平台,我有一个页面,包含多个处方,当点击保存按钮时,会保存处方信息。在保存处方信息的过程中,会保存处方明细信息,会保存收费信息,会保存发药信息。采用循环保存每个处方信息的方式,不同处方之间的保存是同步操作,在同一个线程内,只有一个保存操作执行完成之后,才能执行下一个处方的保存操作。通过分析可知,各个处方的保存并没有依赖关系,如果采用异步的方式,可以大大的提高性能。异步操作开启任务线程执行保存任务,主线程阻塞直到任务线程全部执行完毕或者任意一个任务线程执行失败。只要任意一个任务线程保存失败,则任务线程抛出异常,主线程捕获异常,然后主线程取消所有任务线程的任务执行。同步就这么轻松愉快的改为异步了,那该有多好?

当你任务成功已经很近了,在前方等待的却是失败

代码写完了,开始自测了。添加几个菜单保存,成功,速度提高了一大截,完美!激动之情,纵然像我这样会装的人,还是禁不住溢于言表了。正常情况下可以了,就该试试异常情况了。正常异常都行,才具有可用性。手动抛个Exception类异常,搞了半天,抛不出去,以为是因为用了lambda表达式的问题,又改为常规写法,还是不行,这一搞心都凉了半截!同时又发现当一个任务出现异常,需要终止其它任务时,也没有好的办法,心更凉了。没办法,先就这样了,以后再搞。

鉴于上次留下了两个难题在网上也没查到解决的办法,决定自力更生想办法。于是开始看CompletableFuture源码,试图在源码中找答案。利用休息时间看了几天,而且有时间了,于是再次尝试。一通捣鼓,发现任务线程可以抛RuntimeException,主线程来捕获。能捕获到异常了,那事务机制就能起作用了,不禁为之一振!然后事实证明,我还是太年轻,多个线程执行,当有一个出现异常,并不会使其它线程执行的任务回滚!同时,任务的取消也没有可行的方案。两个难题还是没有解决,通过CompletableFuture进行异步操作的首次尝试最终以失败告终

接下来这方面我还会继续探索,早日在实际开发中使用。