Future
注:下面内容参考Scala CookBook
Future: 在Akka中,Future是一个数据结构,用来检索并发操作的结果。这些操作通常是由Actor或者是Dispatcher直接执行。这些结果可以阻塞(同步),也可以不阻塞(异步)
你可能需要用一种简单的方式去并发的执行多个任务,包括当任务完成的时候对结果进行处理-Future
第一个例子表示了如何去创建一个future,阻塞并等待结果。
future为了执行callback和其它操作,需要ExecutionContext(执行环境),类似与java.util.concurrent.Executor
例子:
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global //导入"default golbal execution context"
//可以将execution context 作为一个线程池(Future并发需要)
object Future1 extends App{
implicit val baseTime = System.currentTimeMillis() //返回系统当前时间
val f = Future { //创建Future 仅仅让块中的代码去执行即可
Thread.sleep(50)
1 + 1
}
val result = Await.result(f,1 second) //等待让Future返回,如果在时间内没有返回,就会报
//java.util.concurrent.TimeoutException
println(result)
Thread.sleep(1000)
}
Run one thing,but don not block—use callback
一个更好的方法就是将future和callback方法一起使用,一共有3个callback方法:
onComplete / onSuccess / onFailure
onComplete
例子:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Random, Success}
object Future1 extends App{
println("starting calculation ...")
val f = Future {
Thread.sleep(Random.nextInt(500))
42
}
println("before onComplete")
f.onComplete {
case Success(value) => println(s"Got the callback, meaning = $value")
case Failure(e) => e.printStackTrace
}
// do the rest of
println("A ...");Thread.sleep(100)
println("B ...");Thread.sleep(100)
println("C ...");Thread.sleep(100)
println("D ...");Thread.sleep(100)
println("E ...");Thread.sleep(100)
println("F ...");Thread.sleep(100)
}
每一次输出的结果Got the callback, meaning = $value在哪个位置都不一样,取决与Thread的睡眠时间。
控制台打印的结果表明:其它工作的代码工作的同时,future也可以进行工作
The onSuccess and Failure callback methods
如果你有时不想用onComplete,你可以使用onSuccess/onFailure
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.Random
object Future1 extends App{
val f = Future {
Thread.sleep(Random.nextInt(500))
val k = Random.nextInt(500)
if (k > 100) throw new Exception("Yikes!" + k) else k
}
f onSuccess {
case result => println(s"Success: $result")
}
f onFailure {
case t => println(s"Exception: ${t.getMessage}")
}
// do the rest of
println("A ...");Thread.sleep(100)
println("B ...");Thread.sleep(100)
println("C ...");Thread.sleep(100)
println("D ...");Thread.sleep(100)
println("E ...");Thread.sleep(100)
println("F ...");Thread.sleep(100)
}
第一个Random决定控制台输出的位置
第二个Random决定输出的是onSuccess的内容还是onFailure的内容
这个例子类似于前面的onComplete例子
Creating a method return a Future[T]
定义一个方法异步计算返回Future,future中保留着结果
import scala.concurrent.{Await, Future, future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
object Futures2 extends App {
implicit val baseTime = System.currentTimeMillis
def longRunningComputation(i: Int): Future[Int] = future {
sleep(100)
i + 1
} //方法返回的future中保留着数据
// this does not block
longRunningComputation(11).onComplete {
case Success(result) => println(s"result = $result")
case Failure(e) => e.printStackTrace
}
// keep the jvm from shutting down
sleep(1000)
}
Run multiple things; something depends on them; join them together
有时候你需要并发的执行几个操作,等待他们去完成,并对他们的结果进行聚合
import scala.concurrent.{Future,future}
import scala.concurrent.ExecutionContext.Implicits.global 类似与Thread pool,用于Future的并行操作
import scala.util.Random
object Cloud{
def runAlgorithm(i:Int):Future[Int] = future {
Thread.sleep(Random.nextInt(500))
val result = i + 10
println(s"returning result from cloud:$result")
result
}
}
object Future1 extends App{
println("starting futures")
//下面三行并行处理
//result1 result2 result3均为Future[Int]类型
val result1 = Cloud.runAlgorithm(10)
val result2 = Cloud.runAlgorithm(20)
val result3 = Cloud.runAlgorithm(30)
println("before for-comprehension")
//当result1 result2 result3全部返回之后
val result = for{
r1 <- result1
r2 <- result2
r3 <- result3
}yield (r1 + r2 + r3)
//返回的是Future,不能被直接打印,借助onSuccess
println("before onSuccess")
result onSuccess{
case result => println(s"total = $result")
}
println("before sleep at the end")
Thread.sleep(2000) //睡眠等待Future返回onSuccess,如果不等待不会输出result的值
}
打印结果:
returning result from cloud:40
returning result from cloud:30
returning result from cloud:20
这三条是不确定的,所以这三条是并行的
total = 90
但是这一条是在最后,因为需要前面3个结果