`

使用future实现内置异步API

阅读更多

当设计并发策略时,要将 "what做什么"和 "how怎么做"进行分离,
Prefer Futures to Baked-In "Async APIs" 一文介绍了如何使用语言的并行API通过异步 来实现这点。

普通同步性质的方法如下:

RetType DoSomething(
  InParameters ins,
  OutParameters outs
);


如果DoSomething 将花费很长时间执行,无论它是否耗费CPU,比如从数据库中加载一个数据就是很耗费时间的,那么是不是在DoSomething执行的同时,我们做做其他事情呢?

比如:
result = DoSomething( this
, that, outTheOther );
OtherWork();


如果OtherWork不依赖result 这个值,那么我们让DoSomething使用通常意义上的异步 执行就没有问题。

但是如果OtherWork依赖上一步执行结果result,怎么办?

第一个方案是使用Begin/End 模式实现:
设计一个开始接口,如下
IAsyncResult BeginDoSomething(
  InParameters ins
);

再设计一个结果接口,如下:
RetType  EndDoSomething(
  IAsyncResult asyncResult,//上一接口计算的结果


  OutParameters outs
);



使用方式如下代码:
IAsyncResult ar = BeginDoSomething( this
, that );
result = DoSomething( this
, that, outTheOther );

//在DoSomething运行同时,执行OtherWork


OtherWork();


//将上面两个融合Join, 


ar.AsyncWaitHandle.WaitOne();
//必要时需要等待


result = EndDoSomething( ar, outtheOther );




这个模式需要在最后等待,无论DoSomething和OtherWork哪个先做完,都要等待对方,这个性能会很差,当然该文从.NET框架等多个角度说明这个模式一些局限,这里不再引述,可以参考原文。

我们主要目的是要将“如何异步 运行这个工作 ”(也就是调用"how如何做")和做什么分离开来。在上面这个案例中,我们关注的是让DoSomething和OtherWork异步启动,而DoSomething如何异步 运行(how),应该不是我们关心的,至少应该从上面这段调用代码中分离出去。而 begin/end 模式并没有帮助我们做到这点,相反是将How和What耦合在一起了。

让我们来看看如何实现How和What分离解耦:
1.使用一个分离的Task任务调用来运行How的工作内容,根据你的语言平台,比如如果是Java/.NET,使用pool.run( /*task*/ ),如果C++0x,使用async( /*task*/ ) .

2.使用futures来管理异步 运行的结果. 这实际就是类Java JDK中的Future<T> API, C++0x标准即将也会有,而.NET下一个版本使用的是Task<T>.

这样,上面案例代码如下:
//第一步 asynchronous call


future<int
> result =
  async( ()=<{ return
 CallSomeFunc(x,y,z); } );



//第二步  code here runs concurrently with CallSomeFunc 



//同时运行其他事情




//第三步 use result when it's ready (this might block)



//在这里使用异步

运行dosomething的结果


DoSomethingWith( result.value() );



这里代码为什么和前面代码不完全一致,因为我们根据How和What分离,更改了设计,如果前面案例的otherwork依赖DoSomething的结果,那么,我们就要将otherwork内容进行分解,将otherwork中不依赖DoSomething结果的内容首先运行,也就是上面第二步,然后,使用在第三步,我们将两个计算结果融合。

这种使用Future特性将How和What分离的模式,已经被使用在Jdonframework   6.2的Domain Events,实际就是Domain Events的内在机制,当领域模型中激活一个事件时,实际就是发送了一个消息,在Jdonframework 中,监听消息实际执行如下代码:
private
 void
 asynExecMessageListener(final
 DomainMessage message) {
 FutureTask futureTask = new
 FutureTask(new
 Callable<Boolean>() {
    public
 Boolean call() throws Exception {
	try
 {
        	message.getMessageListener().action(message);
	} catch
 (Exception e) {
                 ....
		return
 true
;
	}
	});

	message.addFutureTask(futureTask);//运行futuretask


	executor.execute(futureTask);
//相当于pool.run



	}



应该说:JdonFramework 6.2是将EDA和Java并行计算,异步可伸缩性 融合在一起,在设计理念是先进的,本文也可以验证这点。参考Domain Events异步应用

 

原文:http://www.jdon.com/jivejdon/thread/38006

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics