分享更有价值
被信任是一种快乐

如何理解异步编程的Future

文章页正文上

本篇内容介绍了“如何理解异步编程的Future”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!先聊聊线程池的提交方式谈到 Future 的时候,我们基本上就会想到线程池,想到它的几种提交方式。先是最简单的,execute 方式提交,不关心返回值的,直接往线程池里面扔任务就完事:可以看一下 execute 方法,接受一个 Runnable 方法,返回类型是 void:然后是 submit 方法。你知道线程池有几种 submit 方法吗?虽然你经常用,但是可能你从来没有关心过人家。呸,渣男:有三种 submit。这三种按照提交任务的类型来算分为两个类型。提交执行 Runnable 类型的任务。提交执行 Callable 类型的任务。但是返回值都是 Future,这才是我们关心的东西。也许你知道线程池有三种 submit 方法,但是也许你根本不知道里面的任务分为两种类型,你就只知道往线程池里面扔,也不管扔的是什么类型的任务。我们先看一下 Callable 类型的任务是怎么执行的:这里利用 lambda 表达式,直接在任务体里面带上一个返回值,这时你看调用的方法就变成了这个:运行结果也能拿到任务体里面的返回了。输出结果如下:好,接下来再说说 submit 的任务为 Runable 类型的情况。这个时候有两个重载的形式:标号为 ① 的方法扔进去一个 Runable 的任务,返回一个 Future,而这个返回的 Future ,相当于是返回了一个寂寞。下面我会说到原因。标号为 ② 的方法扔进去一个 Ru免费云主机、域名nable 的任务的同时,再扔进去一个泛型 T ,而巧好返回的 Future 里面的泛型也是 T,那么我们大胆的猜测一下这就是同一个对象。如果是同一个对象,说明我们可以一个对象传到任务体里面去一顿操作,然后通过 Future 再次拿到这个对象的。一会就去验证。来,先验证标号为 ① 的方法,我为啥说它返回了一个寂寞。首先,还是先把测试案例放在这里:可以看到,确实是调用的标号为 ① 的方法:同时,我们也可以看到 future.get() 方法的返回值为 null。你说,这不是返回了一个寂寞是干啥?当你想用标号为 ① 的方法时,我劝你直接用 execute 方式提交任务。还不需要构建一个寂寞的返回值,徒增无用对象。接下来,我们看看标号为 ② 的方法是怎么用的:可以看到改造之后,确实是调用了标号为 ② 的方法:future.get() 方法的输出值也是异步任务中我们经过计算后得出的 5201314。你看,渣男就是这样,明明不懂你,还非得用甜言蜜语来轰炸你。呸。好了。综上,线程池的提交方式一共有四种:一种 execute,无返回值。三种 submit,有返回值。submit 中按照提交任务的类型又分为两种:一个是 Callable,一个是 Runable。submit 中 Runable 的任务类型又有两个重载方法:一个返回了个寂寞,一个返回了个渣男。哦,不。一个返回了个寂寞,一个返回了个对象。这个时候就有人要站出来说:你说的不对,你就是瞎说,明明就只有 execute 这一种提交方式。是的,“只有 execute 这一种提交方式”这一种说法也是没错的。请看源码:三种 submit 方法里面调用的都是 execute 方法。能把前面这些方法娓娓道来,从表面谈到内在的这种人,才是好人。只有爱你,才会把你研究透。当然,还有这几种提交方式,用的不多,就不展开说了:好,上面这些东西捋清楚了之后。我们再聚焦到返回值 Future 上:
从上面的代码我们可以看出,当我们想要返回值的时候,都需要调用下面的这个 get() 方法:而从这个方法的描述可以看出,这是一个阻塞方法。拿不到值就在那里等着。当然,还有一个带超时时间的 get 方法,等指定时间后就不等了。呸,渣男。没耐心,这点时间都舍不得等。总之就是有可能要等的。只要等,那么就是阻塞。只要是阻塞,就是一个假异步。所以总结一下这种场景下返回的 Future 的不足之处:只有主动调用 get 方法去获取值,但是有可能值还没准备好,就阻塞等待。任务处理过程中出现异常会把异常隐藏,封装到 Future 里面去,只有调用 get 方法的时候才知道异常了。写到这里的时候我不禁想起一个形象的例子,我给你举一个。假设你想约你的女神一起去吃饭。女神嘛,肯定是要先画个美美的妆才会出去逛街的。而女神化妆就可以类比为我们提交的一个异步任务。假设你是一个小屌丝,那么女神就会对你说:我已经开始化妆了,你到楼下了就给我打电话。然后你就收拾行头准备出发,这就是你提交异步任务后还可以做一些自己的事情。你花了一小时到了女神楼下,打电话给她:女神你好,我到你楼下了。女神说:你先等着吧,我的妆还没画好呢。于是你开始等待,无尽的等待。这就是不带超时时间的 future.get() 方法。也有可能你硬气一点,对女神说:我最多再等 24 小时哈,超过 24 小时不下楼,我就走了。这就是带超时时间的 future.get(timeout,unit) 方法:结果 24 小时之后,女神还没下来,你就走了。当然,还有一种情况就是你到楼下给女神打电话,女神说:哎,今天我男神约我出去看电影,就不和你去吃饭了哈。本来我想提前给你说的,但是我又记不起你电话,只有你打过来我才能告诉你。就这样,你自己玩去吧。这就相当于异步任务执行过程中抛出了异常,而你只有在调用了 get 方法(打电话操作)之后才知道原来异常了。而真正的异步是你不用等我,我好了我就叫你。就像女神接到男神的电话时说的:我需要一点时间准备一下,你先玩自己的吧,我一会好了给你打电话。这让我想起了好莱坞原则:Don’t Call Us,We’ll Call you!接下来,让我们见识一下真正的异步。什么叫真正的:“你先玩自己的,我一会好了叫你。”Guava 的 Future女神说的:“好了叫你”。就是一种回调机制。说到回调,那么我们就需要在异步任务提交之后,注册一个回调函数就行。Google 提供的 Guava 包里面对 JDK 的 Future 进行了扩展:新增了一个 addListenter 方法,入参是一个 Runnable 的任务类型和一个线程池。使用方法,先看代码:首先创建线程池的方式变了,需要用 Guava 里面的 MoreExecutors 方法装饰一下:然后用装饰后的 executor 调用 submit 方法(任意一种),就会返回 ListenableFuture ,拿到这个 ListenableFuture 之后,我们就可以在上面注册监听:所以,上面的程序我们调用的是入参为 callable 类型的接口:从运行结果可以看出来:获取运行结果是在另外的线程里面执行的,完全没有阻塞主线程。和之前的“假异步”还是有很大区别的。除了上面的 addListener 方法外,其实我更喜欢用 FutureCallback 的方式。可以看一下代码,非常的直观:有 onSuccess 方法和 onFailure 方法。上面的程序输出结果为:如果异步任务执行的时候抛出了异常,比如女神被她的男神约走了,异步任务改成这样:最终的运行结果就是这样:是的,女神去看电影了。她一定只是不想吃饭而已。加强版的Future – CompletableFuture第一小节讲的 Future 是 JDK 1.5 时代的产物:经过了这么多年的发展,Doug Lea 在 JDK 1.8 里面引入了新的 CompletableFuture :到了 JDK 1.8 时代,这才是真正的异步编程。CompletableFuture 实现了两个接口,一个是我们熟悉的 Future ,一个是 CompletionStage。CompletionStage接口,你看这个接口的名称中有一个 Stage :可以把这个接口理解为一个任务的某个阶段。所以多个 CompletionStage 链接在一起就是一个任务链。前一个任务完成后,下一个任务就会自动触发。CompletableFuture 里面的方法非常的多。由于篇幅原因,我就只演示一个方法:该方法的执行结果如下:我们执行的时候并没有指定用什么线程池,但是从结果可以看到也是异步的执行。从输出日志中是可以看出端倪的,ForkJoinPool.commonPool() 是其默认使用的线程池。当然,我们也可以自己指定。这个方法在很多开源框架里面使用的还是非常的多的。接下来主要看看 CompletableFuture 对于异常的处理。我觉得非常的优雅。不需要 try-catch 代码块包裹,也不需要调用 Future.get() 才知道异常了,它提供了一个 handle 方法,可以处理上游异步任务中出现的异常:由于女神在化妆的时候,接到男神的电话约她看电影,就只能放你鸽子了。所以,上面程序的输出结果如下:如果,你顺利把女神约出来了,是这样的:“如何理解异步编程的Future”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注云技术网站,小编将为大家输出更多高质量的实用文章!

相关推荐: HTML基础的用法有哪些

本文小编为大家详细介绍“HTML基础的用法有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“HTML基础的用法有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。 1、html标签是用来给文本添加语义的,而不是用来修饰文本的; …

文章页内容下
赞(0) 打赏
版权声明:本站采用知识共享、学习交流,不允许用于商业用途;文章由发布者自行承担一切责任,与本站无关。
文章页正文下
文章页评论上

云服务器、web空间可免费试用

宝塔面板主机、支持php,mysql等,SSL部署;安全高速企业专供99.999%稳定,另有高防主机、不限制内容等类型,具体可咨询QQ:360163164,Tel同微信:18905205712

主机选购导航云服务器试用

登录

找回密码

注册