Vert.x,Core - Future

Future,异步结果

在同步编程(synchronous programming)中,当调用一个方法,方法的调用者(线程)需要一直等待,直到方法结果返回。而在异步编程(asynchronous programming)中,通过异步方法,方法的调用者不需要等待结果返回,当结果就绪时候会通知我们。

In synchronous programming, when a function is called, the caller has to wait until the result is returned. One of the vert.x char­ac­ter­is­tics is being asyn­chro­nous. With an asyn­chro­nous API, you don’t wait for a re­sult, but you are no­ti­fied when this re­sult is ready.

Vert.x的提供的API大都是异步的,调用并不需要等结果返回。我们可以通过设置处理器的方法来处理异步调用,例如前面用到的Vert.x API:

 NetServer connectHandler(Handler<NetSocket> handler); // NetServer NetSocket handler(Handler<Buffer> handler);  // NetSocket long setPeriodic(long delay, Handler<Long> handler) // Vertx

假设一个业务逻辑需要A() -> B() -> C() -> D() 这4个调用来完成,他们调用有向后顺序,后一个调用依赖前一个调用的结果。使用同步编程非常简单,按顺序调用就好了:

resultA = A();
resultB = B(resultA);
resultC = C(resultB);
resultD = D(resultC);

在异步编程中,这个需求会复杂些,因为顺序调用方法不能确保结果返回顺序,异步方法不会等待结果就绪就返回,调用线程将继续往下执行指令。我们可以通过下一个调用嵌套在前一个回调方法内的方式实现:

A(resultA ->{B(resultB ->{C(resultC ->{D(resultC);});});
});

上述异步调用的代码可读性是不是非常差?为此,Vert.x引入Future来承载异步结果,用来代表可能尚未准备好但将来可用的异步结果。Vert.x一些异步方法返回值就是Future,例如前面遇到的Vert.x异步API:

// listen()是异步方法,调用并不需要实际完成端口监听,监听完成后的结果(成功或失败)将放到返回的值Future对象中。
Future<NetServer> listen(); //NetServer

稍微归纳下,Vert.x中,通常使用为对象设置处理器方法来处理(可多次发生)事件,对于只执行一次的操作(如listen)的异步方法,通常返回一个Future对象。需要注意的是,这时两种处理异步结果的方法,不是不互斥的,根据需要选择使用的,也可以同时使用。

Vert.x中的Future对象用于获取异步结果,常用的方法包括:
- boolean isComplete() 判断结果是否就绪,如果结果就绪返回true;
- boolean succeeded() 判断执行是否正常结束,如果正常结束返回true;
- boolean failed() 判断执行是否异常结束(抛异常),如果执行异常返回true;
- T result() 返回正常执行的结果;
- Throwable cause() 返回异常执行抛出的异常;
- Future<T> onComplete(Handler<AsyncResult<T>> handler) 添加一个Handler来通知结果就绪;
- Future<T> onSuccess(Handler<T> handler) 添加一个Handler来处理执行成功的结果;
- Future<T> onFailure(Handler<Throwable> handler) 添加一个Handler来处理器失败;

Promise,异步结果写入

我们可以通过Future获取Vert.x异步调用的结果,那Vert.x是如何将结果放到Future的呢?答案是通过Promise。在Vert.x中, Promise用于在异步调用中写入异步结果。

Promise常用的方法包括:
- void complete() 用于设置异步调用已经结束;
- void complete(T result) 用于设置异步调用已经结束,并写入执行结果;
- void fail(Throwable cause) 用于设置异步调用失败,并写入异常;
- Future<T> future() 返回一个与promise关联的Futre对象,用于将来获取promise写入的值。

Future组合

compose方法作用于顺序组合future。compose方法传入一个函数式接口(JDK 8开始引入),对不常用的同学会有些难涩,稍微讲解以下语法:

Future<U> compose(Function<T, Future<U>> mapper) // Future.compose方法定义// Function是一个接口,有一个抽象方法apply:
public interface Function<T, R> {R apply(T t); // 抽象方法apply接收一个参数T,实现方法必须返回R类型的返回值。
}

对于compose方法的入参Function<T, Future<U>>,假设我们有个值为String类型的Future, 需要通过compose组合另一个Future, 那么代码该如何写?

Future<String> future1 = Future.succeededFuture("Future1 Result."); // 异步调用1, 异步结果是String类型
// 编写一个匿名类, 实现Function接口,接口方法实现返回一个值为Integer的Future.
Function<String, Future<Integer>> function2 = new Function<>() {@Overridepublic Future<Integer> apply(String result) { // result传入的是future1的结果System.out.println("async call 1 result: " + result);// 在这里执行异步调用2, 并返回异步调用2的Futrue ...return Future.succeededFuture(result.length());}
};Future<Integer> future2 = future1.compose(function2);
// 最后,程序输出future2的结果,打印(future结果)字符串"Future1 Result."的长度
future2.onSuccess(result -> System.out.println(result)); 

我们知道,在Java中,如果一个接口只有一个抽象方法,是可以写成lambda表达式的:

Future<Integer> future2 = future1.compose(result -> {System.out.println("async call 1 result: " + result);return Future.succeededFuture(result.length());
});

通过compose方法,可以让异步调用按(组合顺序)顺序执行,而且可以将前一个调用的异步结果做为参数传递给下一个异步调用,如果其中一个异步调用失败(异常),则不会继续执行下去,最后一个Future通知执行异常。

除了compose方法, Future还提供了更多组合方法:map、recover、otherwise、andThen,以及flatMap。这里不做一一介绍。最后,举个含Future,Promise和compose的例子做为总结。

假设我们要启动一个http服务,需要:
1.先从数据库中需要的数据;
2. 根据数据库取出的数据来启动http服务器;

import java.util.logging.Level;
import java.util.logging.Logger;import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;public class Core2 {private static final Logger LOGGER = Logger.getLogger(Core1.class.getName());public static void main(String[] args) {Vertx vertx = Vertx.vertx();Future<String> dbAsyncResult = prepareDatabase(vertx, true);Future<StringBuilder> httpAsyncResult = prepareHttpServer(vertx, dbAsyncResult, false);httpAsyncResult.onComplete(asyncResult -> {if (asyncResult.succeeded()) {LOGGER.info(asyncResult.result().toString());} else {LOGGER.log(Level.SEVERE, "App Boot Failed!", asyncResult.cause());}vertx.close();});}public static Future<String> prepareDatabase(Vertx vertx, boolean fail) {Promise<String> promise = Promise.promise();vertx.setTimer(2000, event -> { // 假设在这里执行Vert.x数据库相关的异步API。if (fail) {promise.fail(new Exception("prepareDatabase failed.")); //如果执行抛异常,这写入异常。} else {LOGGER.info("prepareDatabase done.");promise.complete("Hello Service"); // 执行正常结束,写入结果。}});return promise.future(); // 返回promise的关联futrue对象。}public static Future<StringBuilder> prepareHttpServer(Vertx vertx, Future<String> databaseFuture, boolean fail) {return databaseFuture.compose(databaseResult -> { // composePromise<StringBuilder> promise = Promise.promise();vertx.setTimer(1000, event -> { // 假设在这里执行Vert.x中的http server相关的异步API。if (fail) {promise.fail(new Exception("prepareHttpServer failed."));} else {LOGGER.info("prepareHttpServer done.");StringBuilder buff = new StringBuilder();buff.append(databaseFuture.result()).append(" started.");promise.complete(buff);}});return promise.future();});}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1543707.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

学习记录:js算法(四十三):翻转二叉树

文章目录 翻转二叉树我的思路网上思路递归栈 总结 翻转二叉树 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点 图一&#xff1a; 图二&#xff1a; 示例 1&#xff1a;&#xff08;如图一&#xff09; 输入&#xff1a;root [4,2,7,1…

Python记录

1.冒泡排序 时间复杂度O&#xff08;n^2) 选择、插入都是 def bubble(data, reverse):for i in range(len(data)-1):for j in range(len(data)-i-1):if data[j] > data[j1]:data[j], data[j1] data[j1], data[j]if reverse:data.reverse()return data 2.快速排序 时间…

护理陪护小程序|陪护系统||陪护系统开发

在当今社会&#xff0c;随着人口老龄化的加剧和家庭结构的变化&#xff0c;护理与陪护服务的需求日益增长。为了更好地满足这一市场需求&#xff0c;并提升服务效率与质量&#xff0c;护理陪护小程序应运而生。这类小程序不仅为用户提供了便捷、高效的服务预约与管理平台&#…

828华为云征文 | 云服务器Flexus X实例,Docker集成搭建Redis集群

828华为云征文 | 云服务器Flexus X实例&#xff0c;Docker集成搭建Redis集群 Redis 集群是一种分布式的 Redis 解决方案&#xff0c;能够在多个节点之间分片存储数据&#xff0c;实现水平扩展和高可用性。与传统的主从架构不同&#xff0c;Redis 集群支持数据自动分片、主节点故…

J Transl Med结肠癌分子分型+简单实验

目录 技术路线 实验设计&#xff08;药物敏感性&#xff09; 亮点 方法 从 TCGA 和 GEO 数据库下载大量和单细胞 RNA 测序以及 CRC 的临床数据。HRGs 和 LMRGs 来自分子特征数据库。使用 R 软件包 DESeq2 进行差异表达分析。使用无监督聚类进行分子亚型。使用单变量 Cox 回…

嘉宾云集旌城 只为大赛而来 2024ISGC国际烈酒(中国)大奖赛在德阳落下帷幕

秋高气爽、古蜀之源&#xff0c;迎来第六届国际烈酒&#xff08;中国&#xff09;大奖赛&#xff1b;五谷丰登、重装之都&#xff0c;齐聚百名国际烈酒大奖赛评委。 9月18日&#xff0c;由德阳市人民政府、国家葡萄酒及白酒露酒产品质量检验检测中心、上海合作组织多功能经贸平…

图片压缩怎么弄?教你5种图片压缩小技巧

现如今&#xff0c;图片已成为我们日常生活和工作不可或缺的一部分。然而&#xff0c;高清图片往往伴随着庞大的文件体积&#xff0c;给存储和传输带来诸多不便。这时候我们就需要对图片进行适当的压缩处理&#xff0c;那么该怎么做呢&#xff1f;下面教大家5种图片压缩小技巧&…

GBase 8s 安装手册

没有失败&#xff0c;只有暂时停止成功&#xff01; 一&#xff1a;简介 GBase 8s 产品支持多种处理器平台&#xff0c;除国际主流的 x86_64 处理器&#xff08;包括 Intel 和 AMD&#xff09; 外&#xff0c;全面支持飞腾、鲲鹏、龙芯、兆芯、海光、申威等国产处理器。 GBas…

2025秋招内推|招联金融

【投递方式】 直接扫下方二维码&#xff0c;使用内推码: igcefb 【招聘岗位】 深圳&#xff0c;武汉&#xff1a; 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策划 产品运营 客户体验管理 风险管理 资产管理 【校招流程】 简历投递&#xff1a;9月…

kafka 消费者线程安全问题详细探讨

内容概要 主要内容 常见错误案例 下面这段代码大概逻辑 初始化时 实例化KafkaConsumer, 开启线程拉取消息并且处理 资源释放回调 停止线程、调用kafkaConsumer.close进行资源释放 表面上没有问题&#xff0c;但实际上可能出现线程安全问题&#xff0c;因为poll 和 close 两…

Jetpack Compose 核心组件(Text, Images, Buttons)(6)

导读大纲 1.1 基本组件介绍1.2 Text1.2.1 基本用法1.2.2 设计文字风格 1.3 Image组件1.3.1 从各种来源加载图片1.3.2 关键属性1.3.3 如何加载和显示不同类型的图像1.3.4 内容描述和无障碍访问: 1.4 Button组件1.4.1 基本用法1.4.2 装饰和自定义1.4.3 处理按钮点击1.4.4 重要考虑…

基于python深度学习遥感影像地物分类与目标识别、分割实践技术

我国高分辨率对地观测系统重大专项已全面启动&#xff0c;高空间、高光谱、高时间分辨率和宽地面覆盖于一体的全球天空地一体化立体对地观测网逐步形成&#xff0c;将成为保障国家安全的基础性和战略性资源。未来10年全球每天获取的观测数据将超过10PB&#xff0c;遥感大数据时…

JS惰性函数两种实现方式

惰性函数的本质就是函数重写&#xff0c;所谓惰性载入&#xff0c;指函数执行的分支只会发生一次。那什么时函数重写呢&#xff1f;由于一个函数可以返回另一个函数&#xff0c;因此可以用新的函数在覆盖旧的函数。 惰性函数有两种实现方式&#xff1a; 1、在函数被调用时&am…

案例研究丨国控星鲨利用DataEase释放数据潜能,重塑业务视野

国药控股星鲨制药&#xff08;厦门&#xff09;有限公司&#xff08;以下简称为国控星鲨&#xff09;始创于1952年&#xff0c;前身为厦门鱼肝油厂&#xff0c;距今已经有70余年历史&#xff0c;是国家商务部认定的“中华老字号”企业。2011年&#xff0c;国药控股与厦门轻工集…

2024年国庆小长假即将来临,陪猫咪的同时应该如何清浮毛

在父母眼中我们是不是永远都长不大&#xff1f;每次和他们讨论一点事情就开始吵起来。这不&#xff0c;前两天想着和好久不见的朋友去见面&#xff0c;出门前还要被逼问一番。 去到朋友家&#xff0c;发现朋友养了两只可爱的小猫&#xff0c;一时心动上头&#xff0c;我也转身…

通信工程学习:什么是MANO管理编排

MANO&#xff1a;管理编排 MANO&#xff1a;Management and Network Orchestration&#xff08;管理和网络编排&#xff09;在网络功能虚拟化&#xff08;NFV&#xff09;架构中扮演着至关重要的角色。MANO是一个由多个功能实体组合而成的层次&#xff0c;这些功能实体负责管理…

地图定位流程

用户端在小程序认证通过后会自动进行定位&#xff0c;也可以在首页手动定位&#xff0c;定位成功后用户在查询家政服务项目时会根据定位的城市查询该城市有哪些服务项目。 高德地图配置 小程序端的定位是通过手机的定位模块进行定位&#xff0c;定位成功获取经纬度坐标&#x…

吸烟行为检测、重点区域吸烟检测、吸烟检测算法样本标注

吸烟检测算法主要用于公共场所、工作场所和家庭环境中的吸烟行为监控&#xff0c;通过图像识别技术来检测和识别吸烟行为&#xff0c;以确保环境卫生和公共安全。这种技术可以帮助管理者实时监控吸烟行为&#xff0c;及时采取措施&#xff0c;减少二手烟的危害。 一、技术实现…

55 循环神经网络RNN的实现_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录循环神经网络的从零开始实现[**独热编码**]初始化模型参数循环神经网络模型预测[**梯度裁剪**]训练小结练习 循环神经网络的从零开始实现 import math import torch from torch import nn from torch.nn import functional as F from d2l i…

大数据系统调优:从DAG到单机

目标&#xff1a;优化T10的时效性全局DAG调度层优化&#xff1a;提前任务开始时间&#xff1a; 1. 优化慢结点&#xff1a;T10依赖了T4,T7,T8, 其中T8为瓶颈&#xff0c;如果T8能提前点完成&#xff0c;T10可以早点开始&#xff0c;就能早点完成 2. 快结点做更多预计算…