vertx的Future设计
异步痛点
1.回调地狱(CallBack hell) ; 解决方式 Promise 或 Future
2.执行异步后的结果如何回调currentThread ; 解决方式 Context 设计
3.如何处理依赖多异步的result进行逻辑 ; 解决方案 CompositeFuture
JDK的lib库 Callable和Future 问题
Callable任务可以返回结果,返回的结果可以由Future对象取出,但是调用Future.get()会阻塞当前线程
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
public V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
if (unit == null)
throw new NullPointerException();
int s = state;
if (s <= COMPLETING &&
(s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
throw new TimeoutException();
return report(s);
}
/**
* 等待完成,或者中断、超时
*
* @param timed 定义了超时则为true
* @param nanos 等待时间
*/
private int awaitDone(boolean timed, long nanos)
throws InterruptedException {
final long deadline = timed ? System.nanoTime() + nanos : 0L;
WaitNode q = null;
boolean queued = false;
//轮询查看FutureTask的状态
for (;;) {
if (Thread.interrupted()) {//线程中断
removeWaiter(q);
throw new InterruptedException();
}
int s = state;
if (s > COMPLETING) {//完成或取消状态
if (q != null)
q.thread = null;
return s;
}
else if (s == COMPLETING)//正在set result,Thread “运行状态”进入到“就绪状态”
Thread.yield();
else if (q == null)
q = new WaitNode();
else if (!queued)
queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
q.next = waiters, q);
else if (timed) {
nanos = deadline - System.nanoTime();
if (nanos <= 0L) {
removeWaiter(q);
return state;
}
LockSupport.parkNanos(this, nanos);
}
else
LockSupport.park(this);
}
}
vertx的Future设计
1. Future通过事件注册(EventHandler)回调方式,来解决Thread阻塞问题.
UML图:
Futrue instances 采用FutureFactory生产,基于 SPI 机制:
public class FutureFactoryImpl implements FutureFactory {
private static final SucceededFuture EMPTY = new SucceededFuture<>(null);
/**
* 创建FutureImpl 实例
*/
public <T> Future<T> future() {
return new FutureImpl<>();
}
/**
* 返回一个常量 SucceededFuture 实例
* result本身为null, 可以减少内存开销
*/
public <T> Future<T> succeededFuture() {
@SuppressWarnings("unchecked")
Future<T> fut = EMPTY;
return fut;
}
/**
* 创建一个 SucceededFuture 实例
*/
public <T> Future<T> succeededFuture(T result) {
return new SucceededFuture<>(result);
}
/**
* 创建一个 FailedFuture 实例
*/
public <T> Future<T> failedFuture(Throwable t) {
return new FailedFuture<>(t);
}
/**
* 创建一个 FailedFuture 实例
*/
public <T> Future<T> failureFuture(String failureMessage) {
return new FailedFuture<>(failureMessage);
}
}
多异步的result如何组合(并行变串行)
使用的CompositeFuture,来处理多异步结果组合问题:采用计数器(Counters)的方法来解决 wait 问题
public class CompositeFutureImpl implements CompositeFuture, Handler<AsyncResult<CompositeFuture>> {
private final Future[] results;//定义数组
private int count;//计数器
private boolean completed;//是否完成
private Throwable cause;//错误原因
private Handler<AsyncResult<CompositeFuture>> handler;// 回调 eventHandler
public static CompositeFuture all(Future<?>... results) {
CompositeFutureImpl composite = new CompositeFutureImpl(results);//创建实例
int len = results.length; //获取 futures数组长度
for (int i = ; i < len; i++) {
results[i].setHandler(ar -> {
Handler<AsyncResult<CompositeFuture>> handler = null;
if (ar.succeeded()) {
synchronized (composite) { //添加内存屏障,防止并发问题
composite.count++;
if (!composite.isComplete() && composite.count == len) {//所有future成功
handler = composite.setCompleted(null);
}
}
} else {
synchronized (composite) {//添加内存屏障,防止并发问题
if (!composite.isComplete()) {//任何一个失败就失败
handler = composite.setCompleted(ar.cause());
}
}
}
if (handler != null) {//执行回调EventHandler
handler.handle(composite);
}
});
}
if (len == ) {//判断临界点
composite.setCompleted(null);
}
return composite;
}
}
public static CompositeFuture any(Future<?>... results) {
CompositeFutureImpl composite = new CompositeFutureImpl(results);
int len = results.length;
for (int i = ;i < len;i++) {
results[i].setHandler(ar -> {
Handler<AsyncResult<CompositeFuture>> handler = null;
if (ar.succeeded()) {
synchronized (composite) {
if (!composite.isComplete()) {//任何一个成功
handler = composite.setCompleted(null);
}
}
} else {
synchronized (composite) {
composite.count++;
if (!composite.isComplete() && composite.count == len) {//所有future失败
handler = composite.setCompleted(ar.cause());
}
}
}
if (handler != null) {//执行回调EventHandler
handler.handle(composite);
}
});
}
if (results.length == ) {//判断临界点
composite.setCompleted(null);
}
return composite;
}
private static CompositeFuture join(Function<CompositeFuture, Throwable> pred, Future<?>... results) {
CompositeFutureImpl composite = new CompositeFutureImpl(results);
int len = results.length;
for (int i = ; i < len; i++) {
results[i].setHandler(ar -> {
Handler<AsyncResult<CompositeFuture>> handler = null;
synchronized (composite) {
composite.count++;
if (!composite.isComplete() && composite.count == len) {//处理所有不管失败还是成功
// Take decision here
Throwable failure = pred.apply(composite);
handler = composite.setCompleted(failure);
}
}
if (handler != null) {
handler.handle(composite);
}
});
}
if (len == ) {//{//判断临界点
composite.setCompleted(null);
}
return composite;
}
/**
* 根据下标返回结果
* /
public <T> T resultAt(int index) {
return this.<T>future(index).result();
}
public interface CompositeFuture extends Future<CompositeFuture> {
/**
* 返回list Future.result()
*/
default <T> List<T> list() {
int size = size();
ArrayList<T> list = new ArrayList<>(size);
for (int index = ;index < size;index++) {
list.add(resultAt(index));
}
return list;
}
}
vertx的Future设计的更多相关文章
- 多线程手写Future模式
future模式 在进行耗时操作的时候,线程直接阻塞,我们需要优化这样的代码,让他再启动一个线程,不阻塞.可以执行下面的代码. 这个时候我们就用到了未来者模式 future设计类 只有一个方法 pub ...
- vertx的ShardData共享数据
数据类型 一共4种 synchronous shared maps (local) asynchronous maps (local or cluster-wide) asynchronous loc ...
- vertx模块DeploymentManager部署管理器
DeploymentManager public DeploymentManager(VertxInternal vertx) { this.vertx = vertx; loadVerticleFa ...
- vertx读取配置文件,获得端口号
1:在src/conf目录下创建conf.json { } 2:创建Verticle, config().getInteger("http.port", 8080),将会读取配置文 ...
- 从浏览器输入参数,到后台处理的vertx程序
vertx由于性能较高,逐渐变得流行.下面将一个vertx的入门案例. 添加依赖 <!-- vertx --> <dependency> <groupId>io.v ...
- vertx连接mysql数据库
1:创建一个verticle组件 package jdbcConnection; import io.vertx.core.AbstractVerticle; import io.vertx.core ...
- Netty核心概念(9)之Future
1.前言 第7节讲解JAVA的线程模型中就说到了Future,并解释了为什么可以主线程可以获得线程池任务的执行后结果,变成一种同步状态.秘密就在于Java将所有的runnable和callable任务 ...
- Java网络编程中异步编程的理解
目录 前言 一.异步,同步,阻塞和非阻塞的理解 二.异步编程从用户层面和框架层面不同角度的理解 用户角度的理解 框架角度的理解 三.为什么使用异步 四.理解这些能在实际中的应用 六.困惑 参考文章 前 ...
- Vert.x Core 文档手册
Vert.x Core 文档手册 中英对照表 Client:客户端 Server:服务器 Primitive:基本(描述类型) Writing:编写(有些地方译为开发) Fluent:流式的 Reac ...
随机推荐
- LODOP打印当前日期时间的方法
JS方法直接获取.之前有个详细介绍的博文:LODOP打印用JS获取的当前日期本文也再演示一下,详细介绍见上面链接的博文,该方法此文不做详细介绍. 本文有三段:1.JS获取日期,2,.LODOP的FOR ...
- iOS NSInteger 的输出 %d %ld %zd %ld (long)
NSInteger 输出类型 %zd
- 清北学堂(2019 4 28 ) part 1
今天主要用来铺路,打基础 枚举 没什么具体算法讲究,但要考虑更优的暴力枚举方法,例如回文质数,有以下几种思路: 1.挨个枚举自然数,再一起判断是否是回文数和质数,然而一看就不是最优 2.先枚举质数再判 ...
- Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3) D. Barcelonian Distance 几何代数(简单)
题意:给出一条直线 ax +by+c=0 给出两个整点 (x1,y1) (x2,y2) 只有在x,y坐标至少有一个整点的时 以及 给出的直线才有路径(也就是格子坐标图的线上) 问 两个整点所需要 ...
- MAVEN打包同时引入本地jar包
方法一(pom文件指定jar包目录进行引入) 1.将需要手动引入的包放在项目目录下,如lib目录下: 修改pom文件,引入依赖并且将scope设置为system 2.同时配置maven打包插件 方法二 ...
- [洛谷P1650] 田忌赛马
贪心难题:总结贪心问题的一般思路 传送门:$>here<$ 题意 田忌和齐王各有n匹马,赛马时一一对应.赢+200,输-200,平+0. 问最多多少钱? 数据范围:$n \leq 2000 ...
- 20165223《网络对抗技术》Exp3 免杀原理与实践
目录 -- 免杀原理与实践 免杀原理与实践 本次实验任务 基础知识问答 免杀扫描引擎 实验内容 正确使用msf编码器,msfvenom生成jar等文件,veil-evasion,加壳工具,使用shel ...
- [CTSC2017]网络
[CTSC2017]网络 连一条长度为len的边,使得基环树的直径最小 结论:一定连在某条直径两个点上(否则更靠近不劣) 然后二分答案判定. dp[i]:链上一个点往下延伸的最大深度 考虑对于任意两个 ...
- (转)spring异常抛出触发事务回滚策略
背景:在面试时候问到事务方法在调用过程中出现异常,是否会传递的问题,平时接触的比较少,有些懵逼. spring异常抛出触发事务回滚策略 Spring.EJB的声明式事务默认情况下都是在抛出unchec ...
- sklearn_随机森林random forest原理_乳腺癌分类器建模(推荐AAA)
sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...