在本系列文章第一节中,我曾提及,Stateless Future采用线程无关模型。在线程无关模型中,使用Future宏时,程序员不需要关心JVM的线程模型,只需要关注于执行顺序和逻辑流程。不过,Stateless Future中确实有一些约定,决定了线程切换的行为。
Future宏的线程约定
Future宏的功能是把源代码中每一处await调用替换成onComplete调用。每一处await调用以后的所有代码,都会被转换成回调函数,作为参数传给onComplete。
例如,给定以下代码:
val future1 = Future {
beforeAwait()
val resultOfFuture2 = future2.await
afterAwait()
"result of future1"
}
大体相当于
val future1 = new Future.Stateless {
// 注意:真正的Future宏生成onComplete而非foreach。
// 为了简化代码,本示例使用foreach代替onComplete,相当于不支持尾调用功能的onComplete
def foreach(handler: String => Unit)(implicit catcher: Catcher[Unit]) = {
beforeAwait()
// 注意:真正的Future宏使用onComplete而非foreach。
future2.foreach { resultOfFuture2 =>
afterAwait()
handler("result of future1")
}
}
}
要获取future1
的结果时,类似for (resultOfFuture1 <- future1) { println(resultOfFuture1) }
的代码会被编译器转换成future1.foreach { resultOfFuture1 -> println(resultOfFuture1) }
1。所以,future1
内,future2.await
上方的代码beforeAwait()
,就会在当前线程立即执行。这样就得到了第一个结论:Future宏内的首处await以前的所有代码,都在当前线程立即执行。
而afterAwait()
位于future2.await
,所以会被Future宏捕获到回调函数中,由于这个回调函数作为参数传给future2
,所以回调函数什么时候触发,在哪个线程中触发,就由future2
决定了。这样就得到了第二个结论:Future宏内每一处xxxFuture.await
以后的代码,由xxxFuture
决定在哪个线程中执行。
最后,注意Future宏生成了handler("result of future1")
用来触发handler
以告知future1
的结果。这行代码和afterAwait()
一样,也位于回调函数中。这样就得到了第三个结论:Future宏内最后一处await决定了Future宏的结果在哪个线程中处理。
总结Future宏对线程模型的约定如下:
- Future宏内的首处await以前的所有代码,都在当前线程立即执行。
- Future宏内每一处
xxxFuture.await
以后的代码,由xxxFuture
决定在哪个线程中执行。 - Future宏内最后一处await决定了Future宏的结果在哪个线程中处理。
- 栏目
- 程序设计 (7)