直接上示例:
获取一个Futute:
def getFuture3: Future[String] = {
FuturePool.unboundedPool {
println("begin future3")
println(Thread.currentThread().getName)
TimeUnit.SECONDS.sleep(3)
println("future3 over.")
"zero"
}
}
类似Java,在线程池里提交一个任务,返回值即 { } 中的值。注意这里的线程池是twitter中的UnboundedFuturePool(无界任务池),当然可以指定线程池:
def getFuture2: Future[String] = {
val executors = Executors.newFixedThreadPool(3)
val futurePool: ExecutorServiceFuturePool = FuturePool.apply(executors)
futurePool.apply({
//使用的是自定义的pool
println("begin future2")
println("future2 --- " + Thread.currentThread().getName)
TimeUnit.SECONDS.sleep(3)
println("future2 over.")
"zero"
})
}
这里指定了executors线程池,那个任务执行由指定池中的线程去完成。如果需要get这个future的值:
val result = Await.result(getFuture3, DEFAULT_TIMEOUT)
组合两个future的结果为另一个future,test2也是同样:
def test1: Unit = {
val future3 = for (f1 <- getFuture1; f2 <- getFuture2) yield (f1 + " " + f2)
println("await")
val result = Await.result(future3, DEFAULT_TIMEOUT)
println(result)
}
运行结果:
begin future1
await
future1 --- UnboundedFuturePool-1
future1 over.
begin future2
future2 --- pool-1-thread-1
future2 over.
zero zero
从运行结果,效果上看for中内容还是串行执行,但 future3 与 println("await") 是并行执行的,方式二:
def combine(a: String, b: String): Future[String] = {
FuturePool.unboundedPool {
println(s"combine $a + $b")
TimeUnit.SECONDS.sleep(1)
a + "-" + b
}
}
def test2: Unit = {
val result =
for (
result1 <- getFuture1;
result2 <- getFuture2;
combineResult <- combine(result1, result2)
) yield combineResult
println("await")
val v = Await.result(result)
println(v)
}
运行结果:
begin future1
future1 --- UnboundedFuturePool-1
await
future1 over.
begin future2
future2 --- pool-1-thread-1
future2 over.
combine zero + zero
zero-zero
可以看到,使用for来组合两个future的结果时,得是getFuture1完成后getFuture2才开始,是一个串行调用。有其他方式么?
def test3: Unit = {
val future3 = Future.join(getFuture1, getFuture2)
val f = future3 flatMap { e =>
combine(e._1, e._2)
}
println("await")
println(Await.result(f))
}
运行结果:
begin future1
future1 --- UnboundedFuturePool-1
begin future2
future2 --- pool-1-thread-1
await
future1 over.
future2 over.
combine zero + zero
zero-zero
可以看出Future.join比for要好,是真正的异步并发。当然Future还可以处理异常:
def fail(a: String, b: String): Future[String] = {
FuturePool.unboundedPool {
println("fail operation.")
TimeUnit.SECONDS.sleep(1)
println("throwing exception!")
throw new Exception("Exception.")
}
}
//抛出异常并被捕获
def test4: Unit = {
val result = Future.join(getFuture1, fail("a", "b")).flatMap {
case (result1, result2) => combine(result1, result2)
}.ensure {
//Ensure is executed both in case of succes or failure.
println("---ensure----")
}.rescue {
//Only execute when exception occurred
case e: Exception => {
println(e.getMessage)
Future.False
}
}
println("await")
println(Await.result(result))
}
运行结果:
fail operation.
begin future1
future1 --- UnboundedFuturePool-1
await
throwing exception!
---ensure----
Exception.
false
rescue块可以处理异常,也仅在异常发生时执行,ensure无论是正常还是异常都会执行。