注册 登录  
 加关注

网易博客网站关停、迁移的公告:

将从2018年11月30日00:00起正式停止网易博客运营
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

为着理想勇敢前进

 
 
 

日志

 
 

基于Stateless Future的Scala异步编程(二)欠条  

2014-07-02 22:28:48|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

本文首发在岂凡技术小站


Future是指尚未完成的操作。在异步编程中,这些操作结果将来会在操作完成后,再传给回调函数。换句话说,一个Future对象,就是一张将来可能兑现的欠条

兑现欠条

有两种语法等待一张欠条兑现,awaitfor推导式1风格。

await等待欠条兑现

调用await方法的语义是导致执行流暂停,一直等到欠条兑现才返回。await的返回值就是欠条兑现的结果。我在前一节中讲过,await会被Future宏替换成onComplete,并不真正阻塞线程:

Nio2Future.connect(socket, new InetSocketAddress("www.qifun.com", 80)).await

readAll(socket, response).await

writeAll(socket, request).await

在上述例子中,await表示顺序等待操作,必须出现在Future块中。如果在Future外使用await,就会导致`await` must be enclosed in a `Future` block的编译错误。

嵌套函数

需要注意,在Future块中的内嵌函数中,一般也不能用await

val myFuture = Future { def nestedFunction() = { anotherFuture.await // 编译错误! } nestedFunction() }

幸好Future可以嵌套,所以你可以这样写:

val myFuture = Future { def nestedFunction() = Future { anotherFuture.await // 编译通过 } nestedFunction().await }

for等待欠条兑现

欠条兑现的另一语法借用了Scala的for关键字:

println("即将开始等待myFuture") for (result <- myFuture) { println(s"结果是:$result") } println("正在等待myFuture……")

注意,此处的for语句并不是循环!for代码块内是欠条兑现后才触发的代码,通常只触发一次。而for代码块之后的代码则在开始等待myFuture以后,马上执行。

所以,大多数情况下,上述代码的输出顺序将会类似这样:

即将开始等待myFuture 正在等待myFuture…… 结果是:<myFuture兑现后的结果>

等待多张欠条

还可以用for语句顺序等待多张欠条:

println("即将开始等待myFuture1") for (result1 <- myFuture1; result2 <- getMyFuture2(result1)) { println(s"结果是:$result1、$result2") } println("正在等待myFuture1和getMyFuture2(result1)……")

上述代码中,两张欠条依次等待。其中第二张欠条getMyFuture2(result1)甚至是利用第一张欠条的兑现结果result1才能计算得到。

欠条的映射和合并

你也可以用for/yield语法,把多张欠条合成一张:

case class MyResult(result1: Result1, result2: Result2) val myFuture3: Future[MyResult] = for (result1 <- myFuture1; result2 <- getMyFuture2(result1)) yield { MyResult(result1, result2) }

for/yield创建的欠条,属于无状态欠条,支持惰性执行。创建这张新欠条时并不会发起myFuturegetMyFuture2(result1)所对应的异步操作,而要等到对新欠条调用await或者不含yieldfor时,才会发起操作:

for (result3 <- myFuture3) { println(s"最终结果是:${result3.result1}、${result3.result2}") }

当然,你也可以用前面学过的Future/await来合并欠条。以下代码与上方的for/yield示例,功能完全相同:

case class MyResult(result1: Result1, result2: Result2) val myFuture3: Future[MyResult] = Future[MyResult] { val result1 = myFuture1.await val result2 = getMyFuture2(result1).await MyResult(result1, result2) }

(待续。下一节将会讲解无状态欠条和有状态欠条的区别。)


  1. for推导式For Comprehension。Scala的for推导式语法类似命令式语言的for循环,但语义却更接近Ruby、Python等语言的列表推导式(List Comprehension)。 ?

  评论这张
 
阅读(615)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018