Scala 异步编程之 Future

同步异步,阻塞非阻塞,在IO模型中几个概念组合在一起不是很容易理解,但是只从代码执行的角度看同步异步是很清晰的:

同步代表这段代码中的逻辑必须执行完毕,而异步代表调用马上返回,但通常情况下是获取不到需要的值。

同步:val  value={

Thread.sleep(2000)

1

}

异步: val value=Future{

Thread.sleep(2000)

1

在scala repl执行上面代码可以发现同步等待两秒后返回结果 Int 1,而异步马上返回了

value: scala.concurrent.Future[Int] = List()。

注意:在shell中必须导入 (1)import scala.concurrent.Future 以及 (2) import scala.concurrent.ExecutionContext.Implicits.global

导入(1)是因为需要使用Future,(实际上使用了Future.apply方法),导入(2)则是由异步编程的内在逻辑决定的。

同步方法中的逻辑是由main主线程逐步执行的,而异步编程的思路是:

在执行Future.apply{异步代码块}时,主线程将异步代码块交给新的线程,新起的线程负责异步代码块的计算,而主线程则解放出来,执行下一步。

在scala的Future中,apply方法如下:

def apply[T](body: =>T)(implicit executor: ExecutionContext): scala.concurrent.Future[T] 

我们导入(2) import scala.concurrent.ExecutionContext.Implicits.global,实际上这是scala提供的默认的work-stealing thread pool,我们也可以explicitly地申明:

import scala.concurrent.ExecutionContext

implicit lazy val workStealingPoolExecutionContext: ExecutionContext = {  
    val workStealingPool :ExecutorService = Executors.newWorkStealingPool
    ExecutionContext.fromExecutor(workStealingPool)
}

将implicit 的 ExecutionContext  传给了Future中的(implicit executor: ExecutionContext),使用lazy是为了节约资源,即使我们实现了ExecutionContext ,但实际上不会马上申请线程占用资源,只有真正调用Future方法时,才会执行lazy后面的代码。

在获取future值得时候,我们可以用阻塞的方式,也可以使用回调。

阻塞:

import scala.concurrent.duration._
import scala.concurrent.Await
val resultValue= Await.result(value, 2 seconds)

result的方法如下

   def result[T](awaitable: Awaitable[T], atMost: Duration): T =
      blocking(awaitable.result(atMost)(AwaitPermission))
  }

传入最大等待时长,在这期间阻塞获取future的值,超时后报错,通常用于测试用例。

回调:

value onComplete {  
case Success(intValue) =>  println("success:   "+intValue)  
case Failure(error) => println("An error has occured: " + error.getMessage)  
}  

可以通过模式匹配的方式获取值。





猜你喜欢

转载自blog.csdn.net/onwingsofsong/article/details/77919274