美文网首页
Scala 异步编程之 Future

Scala 异步编程之 Future

作者: onwingsofsong | 来源:发表于2018-09-24 10:02 被阅读251次

    同步异步,阻塞非阻塞,在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)  

    }  

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

    实际上java 在jdk1.5后增加了callable,也实现了Future,但是java的Future只能通过阻塞等待结果,而scala中的Oncomplete,OnSuccess等回调能充分地利用多核。

    相关文章

      网友评论

          本文标题:Scala 异步编程之 Future

          本文链接:https://www.haomeiwen.com/subject/wlucoftx.html