场景描述:

现在我们考虑用两种方式来实现远程rpc调用:

方案一:采用同步阻塞方式,单个线程按顺序做所有的事情,没有什么特别的,不赘述。

方案二:采用异步方式,对3和4分别创建一个异步线程去做(这样做可能有点作,只是为了演示,勿喷)。

如果采用方案二,最麻烦的地方在于4是依赖3的,意味着4必须等到3返回之后才开始,等到4返回之后,才开始5。可以理解为在3之后还有一个处理链(pipeline),下一个节点根据上一个节点的返回值进行处理。

想想如果我们用netty,应该需要在messageReceived中接收消息后,再启动另一个线程,然后在该线程的messageReceived方法中接收消息后,再做反序列化等后继操作。如果不愿意这么做,自己定义一个状态机也可以的。

有没有一种优雅的,更易理解和易管理的方式来实现呢?

答案当然是有!

async包提供了一种线程安全的异步处理机制,该机制基于Twisted的pythonDeferred API,该API不需要显式定义有限状态机,采用一种简单优雅的方式来管理异步和动态pipeline(处理链)。

其中包含的类很少,其中主要的类为Deferred.class,基本上看懂了这个类就OK了。

Deferred和Future最大的差异是Deferred包含了一个callback链,能够在结果返回后进行一系列的操作。

Deferred机制包含如下特征:

•由动态callback链组成,当deferred结果返回时,该链开始逐个按顺序触发,只有当上一个环节执行并返回结果后,下一个环节才继续执行,如果发生错误则切换到错误处理链。

•包含正常和异常两个处理链,异常链用于处理异常和错误,异常链仅能捕获Exception,不能捕获Throwable和Error。

•Deferred本身并不创建Thread线程,仅提供状态机和多个callback之间切换管理的机制。

内部提供了一个有限状态机,如下:

新增Deferred对象(假设名称为D1)时,状态为Pending;当开始执行callback时,状态变为Running;若某个callback返回的结果为Deferred对象(假设名称为D2),则进入该D2对象中继续执行callback链,此时上一个D1对象的状态为Paused,若D2对象中所有的callback执行完毕,则返回D1对象,D1对象的状态变为Running,所有callback执行完毕后,D1状态变为Done,然后D2状态变为Done。

示例代码:

packagecom.ioe.metric.reader;

importjava.util.concurrent.Executors;

importjava.util.concurrent.locks.Lock;

importjava.util.concurrent.locks.ReentrantLock;

importcom.ioe.common.cache.LocalCache;

importcom.stumbleupon.async.Callback;

importcom.stumbleupon.async.Deferred;

publicclassCacheTest {

publicstaticvoidmain(String[]args)throwsInterruptedException {

CacheTesttest=newCacheTest();

test.getValue("test");

}

privateLocalCachelocalCache=newLocalCache(3600 * 1000L,

100000L);

privateLocklock=newReentrantLock();

// Callback中第一个泛型参数为内部的call方法返回值类型,第二个为内部的call方法入参类型

publicclassServerQueryimplementsCallback,String> {

@Override

publicDeferred call(finalStringkey)throwsException {

//需要等异步线程返回后,才能把获取的值返回

finalDeferredd=newDeferred();

d.addCallback(newCallback() {

@Override

publicString call(Strings)throwsException {

System.out.println("query index server:"+s);

returns;

}

});

Executors.newSingleThreadExecutor().execute(newRunnable() {

@Override

publicvoidrun() {

d.callback(queryServerFromRemote(key));

}

});

returnd;

}

privateString queryServerFromRemote(Stringkey) {

return"10.1.10.100";

}

}

publicclassDataQueryimplementsCallback,String> {

Stringdata=null;

@Override

publicDeferred call(finalStringserver)throwsException {

//需要等异步线程返回后,才能把获取的值返回

finalDeferredd=newDeferred();

d.addCallback(newCallback() {

@Override

publicString call(Strings)throwsException {

System.out.println("query data success:"+s);

returns;

}

});

Executors.newSingleThreadExecutor().execute(newRunnable() {

@Override

publicvoidrun() {

d.callback(queryDataFromRemote(server));

}

});

returnd;

}

/**

*@paramserver

*@return

*/

protectedString queryDataFromRemote(Stringserver) {

return"xxxxxxx";

}

}

publicclassDecodeimplementsCallback {

@Override

publicTest call(Stringdata)throwsException {

System.out.println("try to decode the data.");

finalTestobject= decode(data);

returnobject;

}

/**

*@paramdata

*@return

*/

privateTest decode(Stringdata) {

returnnewTest("hahah");

}

}

privateTest getDataFromRemote(Stringkey) {

Testvalue=null;

try{

lock.lock();

value=localCache.get(key);

if(null==value) {

//定义一个pipeline处理链

// Deferred.fromResult(key)表示根据key来创建一个Deferred对象,返回类型会自动推断为Test

//如果使用Deferred d = new

// Deferred();然后d.callback(key);你就悲剧了

//发现怎么也编译不通过,类型还要强制转换,泛型推断不能起作用

value= Deferred.fromResult(key)

.addBothDeferring(newServerQuery())

.addBothDeferring(newDataQuery())

.addBoth(newDecode()).joinUninterruptibly();

//上面的代码形成了3个Deferred对象,其中ServerQuery一个D1,

//后面的.addBothDeferring(newDataQuery()).addBoth(new

// Decode())形成了另一个D2,

//然后在D2内部还有一个DataQuery形成的Deferred对象D3

//执行顺序为D1、D2(第一个callback后调到D3)、D3、D2(D3中callback执行完毕后,回到D2),结束顺序为D1、D2、D3

System.out.println("put data to cache. value:"+value);

localCache.put(key,value);

}

}catch(Exceptione) {

e.printStackTrace();

}finally{

lock.unlock();

}

returnvalue;

}

publicclassTest {

Stringname;

publicTest(Stringname) {

this.name=name;

}

@Override

publicString toString() {

returnname;

}

}

publicTest getValue(Stringkey) {

Testvalue=localCache.get(key);

if(null==value) {

value= getDataFromRemote(key);

}

returnvalue;

}

}

聊斋java_Deferred,一种Java异步管理机制相关推荐

  1. java中创建类的时候有没有分配内存,你必须了解的java内存管理机制(一)-内存分配...

    前言 在上一篇文章中,我们花了较大的篇幅去介绍了JVM的运行时数据区,并且重点介绍了栈区的结构及作用,相关内容请猛戳!在本文中,我们将主要介绍对象的创建过程及在堆中的分配方式.from 你必须了解的j ...

  2. 浅析java内存管理机制

    内存管理是计算机编程中的一个重要问题,一般来说,内存管理主要包括内存分配和内存回收两个部分.不同的编程语言有不同的内存管理机制,本文在对比C++和java语言内存管理机制的不同的基础上,浅析java中 ...

  3. java内存管理机制剖析(一)

    最近利用工作之余学习研究了一下java的内存管理机制,在这里记录总结一下. 1.1 java内存区域 当java程序运行时,java虚拟机会将内存划分为若干个不同的数据区域,这些内存区域创建和销毁的时 ...

  4. java内存管理机制-转载保存有价值的东西

    JAVA 内存管理总结 1. java是如何管理内存的 Java的内存管理就是对象的分配和释放问题.(两部分) 分配 :内存的分配是由程序完成的,程序员需要通过关键字new 为每个对象申请内存空间 ( ...

  5. Java类管理机制——包的详解

    目录 前言: 一.包的概念 二.包的定义 (1)语法 (2)命名规则 (3)命名规范 三.包的引用 (1)加载需要使用的类 (2)加载整个包 (3)直接使用包名.类名作为前缀 (4)常用包 四.Cla ...

  6. JAVA内存管理机制

    在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这两方面工作都是由JVM自动完成的,降低了Java程序员的学习难度,避免了像C/C++直接操作内存的危险.但是,也正 ...

  7. 聊斋2聂小倩java华语版,[转载]《聊斋志异》2.聂小倩(二)蒲松龄 著  宋德利 译...

    <聊斋志异>2. 聂小倩(二) Strange Tales of a Lonely Studio·Pretty Girl and Lonely Soul 蒲松龄著 宋德利译 5. 原文: ...

  8. 聊斋2聂小倩java华语版,九个版本的聂小倩,看全的没有几个,经典也不是王祖贤!...

    原标题:九个版本的聂小倩,看全的没有几个,经典也不是王祖贤! 在娱乐圈一个经典的素材经常会拿来翻拍,也叫IP.<倩女幽魂>这个大IP就多次翻拍过,给投资方传的盆满钵满.最先接触的87年的& ...

  9. 聊斋2聂小倩java华语版,【聊斋故事汇】之聂小倩(篇二)

    第二日,宁采臣恐怕燕赤霞有事外出,便趁早找他相会.还准备好酒菜,请他一起喝酒.宁采臣暗地观察燕赤霞,心道:小倩说燕赤霞是位奇人异士,为何我端端看不出呢?宁采臣想着小倩的话,不得不硬着头皮说自己晚上害怕 ...

最新文章

  1. Windows Server2016 安装及配置DFS实现数据复制
  2. ubuntu-基本命令篇-12-磁盘管理
  3. linux shell只读变量、删除变量
  4. iOS开发之检查更新
  5. Java高级工程师实战经验图谱
  6. svm预测结果为同一个值_SVM算法总结
  7. 重磅!Yolo v4横空出世!刚刚开源!
  8. 如何让.Net控件在设计时InitializeComponent()中不生成相关代码
  9. 通过js引用外部脚本(嘿嘿,方便直接在浏览器上调试抓取代码)
  10. OSPF开销值、协议优先级及计时器的修改
  11. 方正飞鸿中间件大赛落幕 大学生项目获收购
  12. PS实现割掉狗熊耳朵流血效果
  13. MAC版“迅雷 意外退出”
  14. PTA团体程序设计天梯赛-练习集(3)
  15. 老挑毛 win7 linux,老挑毛u盘装系统步骤|老挑毛u盘一键装系统
  16. JavaScript中的常用浏览器对象
  17. 测试个人禀赋的软件,中医体质自测,个人体质测试,体质健康测试,测试自己的体质...
  18. 如何下载建外街道卫星地图高清版大图
  19. 使用IDL显示DICOM文件的信息
  20. 如何从零开始学习3D视觉?

热门文章

  1. java中字节码_Java字节码浅析(—)
  2. Oracle-索引分裂研究
  3. 下载丨Oracle 11g 安装后参数规范设置
  4. MySQL修改有存量数据的数据库字符集实战
  5. 开发中常见的Oracle三大故障与调优方法
  6. APP搜索如何又快又准?
  7. 高职高考全国计算机证书查询,2017年广东3+证书(高职高考)录取结果查询入口:附广东3+证书(高...
  8. 字体感觉小了 引入的vant_动态字体海报如何设计与制作?
  9. mint linux qq,linuxmint系统下安装QQ
  10. TeXstudio中文编码踩坑实录