基于Future宏的线程约定,Stateless Future的工具库额外提供了几个类,帮助程序员控制线程模型。

JumpInto

JumpIntoFuture宏中的代码切到指定的线程池中运行。

import java.util.concurrent.Executors
val executor = Executors.newSingleThreadExecutor // 创建单线程的线程池

import com.qifun.statelessFuture.Future
val future1 = Future[String] {
  println(s"Current thread name is ${Thread.currentThread.getName} before JumpInto.")
  import com.qifun.statelessFuture.util.JumpInto
  JumpInto(executor).await // 切换到线程池executor
  println(s"Current thread name is ${Thread.currentThread.getName} after JumpInto.")
  "RESULT"
}

println("Before starting future1")

implicit def catcher = PartialFunction.empty
for (result <- future1) {
  println(s"Result of future1 is $result.")
}

println("After starting future1")

以上代码将会输出

Before starting future1
Current thread name is run-main-0 before JumpInto.
After starting future1
Current thread name is pool-15-thread-1 after JumpInto.
Result of future1 is RESULT.

从输出可以知道,调用JumpInto以前的代码运行在run-main-0线程,而调用JumpInto以后的代码运行在pool-15-thread-1线程。

JumpInto配合单线程的线程池,就构成了一个轻量级的消息队列,可以保证跳入了同一个线程池的代码都顺序进行,不会相互打断。JumpInto常常可以用来代替synchronized锁。

Sleep

Sleep类似JumpInto,也能切换线程池。但Sleep会延后一段时间才继续执行后续代码,而不像JumpInto那样立即切换线程。

import java.util.concurrent.Executors
// 创建支持延后执行服务的单线程线程池
val executor = Executors.newSingleThreadScheduledExecutor

import com.qifun.statelessFuture.Future
val future1 = Future[String] {
  println(s"Current thread name is ${Thread.currentThread.getName} before Sleep.")
  import com.qifun.statelessFuture.util.Sleep
  import scala.concurrent.duration._
  Sleep.apply(executor, 2.seconds).await // 2秒后切换到线程池executor
  println(s"Current thread name is ${Thread.currentThread.getName} after Sleep.")
  "RESULT"
}

println("Before starting future1")

implicit def catcher = PartialFunction.empty
for (result <- future1) {
  println(s"Result of future1 is $result.")
}

println("After starting future1")

输出和JumpInto的例子差不多

Before starting future1
Current thread name is run-main-0 before Sleep.
After starting future1
Current thread name is pool-13-thread-1 after Sleep.
Result of future1 is RESULT.

二者区别在于Sleep的例子会在输出After starting future1后停顿两秒,然后再继续输出剩下的信息。


杨博

岂凡 游戏架构师