Scala之Future
一、简介
Future提供了一套高效便捷的非阻塞并行操作管理方案。其基本思想很简单,所谓Future,指的是一类占位符对象,用于指代某些尚未完成的计算的结果。一般来说,由Future指代的计算都是并行执行的,计算完毕后可另行获取相关计算结果。以这种方式组织并行任务,便可以写出高效、异步、非阻塞的并行代码。
所谓Future,是一种用于指代某个尚未就绪的值的对象。而这个值,往往是某个计算过程的结果:
(1)若该计算过程尚未完成,我们就说该Future未就位;
(2)若该计算过程正常结束,或中途抛出异常,我们就说该Future已就位。
Future的就位分为两种情况:
(1)当Future带着某个值就位时,我们就说该Future携带计算结果成功就位。
(2)当Future因对应计算过程抛出异常而就绪,我们就说这个Future因该异常而失败。
Future的一个重要属性在于它只能被赋值一次。一旦给定了某个值或某个异常,future对象就变成了不可变对象——无法再被改写。
二、创建Future
创建future对象最简单的方法是调用future方法,该future方法启用异步(asynchronous)计算并返回保存有计算结果的futrue,一旦该future对象计算完成,其结果就变的可用。
下面,我们举一个例子来说明。假设我们使用某些流行的社交网络的假定API获取某个用户的朋友列表,我们将打开一个新对话(session),然后发送一个请求来获取某个特定用户的好友列表。
import scala.concurrent._
import ExecutionContext.Implicits.global val session = socialNetwork.createSessionFor("user", credentials)
val f: Future[List[Friend]] = Future {
session.getFriends()
}
在上述例子中,然后我们初始化一个session变量来用作向服务器发送请求,用一个假想的 createSessionFor 方法来返回一个List[Friend]。为了获得朋友列表,我们必须通过网络发送一个请求,这个请求可能耗时很长。这能从调用getFriends方法得到解释。为了更好的利用CPU,响应到达前不应该阻塞(block)程序的其他部分执行,于是在计算中使用异步。future方法就是这样做的,它并行地执行指定的计算块,在这个例子中是向服务器发送请求和等待响应。一旦服务器响应,future f 中的好友列表将变得可用。
三、回调函数(Callbacks)
我们都知道Java中的Future并不是全异步的,当你需要Future里的值的时候,你只能用get去获取它,亦或者不断访问Future的状态,若完成再去取值,但其意义上便不是真正的异步了,它在获取值的时候是一个阻塞的操作,当然也就无法执行其他的操作,直到结果返回。
但是在Scala中虽然也可以这么做,但是不推荐,因为Scala的Future提供了回调函数来获取它的结果。看如下例子:
val fut = Future {
  Thread.sleep(1000)
  1 + 1
}
fut onComplete {
  case Success(r) => println(s"the result is ${r}")
  case _ => println("some Exception")
}
println("I am working")
Thread.sleep(2000)
执行结果如下:
I am working
the result is 2从结果中可以看出,我们在利用Callback方式来获取Future结果的时候并不会阻塞,而只是当Future完成后会自动调用onComplete,我们只需要根据它的结果再做处理即可,而其他互不依赖的操作可以继续执行不会阻塞。
四、Future组合
前面我们讲的较多的都是单个Future的情况,但是在真正实际应用时往往会遇到多个Future的情况,那么在Scala中是如何处理这种情况的呢?
我们首先来看下面这个例子,假设我们有一个用于进行货币交易服务的API,我们想要在有盈利的时候购进一些美元。让我们先来看看怎样用回调来解决这个问题。具体代码如下:
val rateQuote = Future {
  connection.getCurrentValue(USD)
}
rateQuote onSuccess { case quote =>
  val purchase = Future {
    if (isProfitable(quote)) connection.buy(amount, quote)
    else throw new Exception("not profitable")
  }
  purchase onSuccess {
    case _ => println("Purchased " + amount + " USD")
  }
}
从上面的代码中,我们可以看出,为了实现功能,我们将不得不在onSuccess的回调中重复这个模式,从而可能使代码过度嵌套,过于冗长,并且难以理解。另一方面,purchase只是定义在局部范围内–它只能被来自onSuccess内部的回调响应。这也就是说,这个应用的其他部分看不到purchase,而且不能为它注册其他的onSuccess回调,比如说卖掉些别的货币。
为解决上述的两个问题,futures提供了组合器(combinators)来使之具有更多易用的组合形式。映射(map)是最基本的组合器之一。下面我们看看重构后的代码如下:
val rateQuote = Future {
  connection.getCurrentValue(USD)
}
val purchase = rateQuote map { quote =>
  if (isProfitable(quote)) connection.buy(amount, quote)
  else throw new Exception("not profitable")
}
purchase onSuccess {
  case _ => println("Purchased " + amount + " USD")
}
我们可以看出,通过对rateQuote的映射我们减少了一次onSuccess的回调,更重要的是避免了嵌套。这时如果我们决定出售一些货币就可以再次使用purchase方法上的映射了。除了map组合器,Ftuture还提供了Future还拥有flatMap,filter和foreach等组合器。
Scala之Future的更多相关文章
- scala(二) Future执行逻辑解读
		在scala中是没有原生线程的,其底层使用的是java的Thread机制.但是在scala中对java Thread进行了封装,实现了更便于操作线程的Future. 官方文档: Futures pro ... 
- scala akka Future 顺序执行 sequential execution
		对于 A => B => C 这种 future 之间的操作,akka 默认会自动的按照顺序执行,但对于数据库操作来说,我们希望几个操作顺序执行,就需要使用语法来声明 有两种声明 futu ... 
- Scala之Future超时
		最近在开发中使用akka http进行请求,返回的是一个future,并且要对future进行超时设置,不知怎么设置,因此学习了下. 一.Future阻塞 首先,scala中的future不支持内置超 ... 
- SDP(13): Scala.Future - far from completion,绝不能用来做甩手掌柜
		在前面几篇关于数据库引擎的讨论里很多的运算函数都返回了scala.Future类型的结果,因为我以为这样就可以很方便的实现了non-blocking效果.无论任何复杂的数据处理操作,只要把它们包在一个 ... 
- 混合使用ForkJoin+Actor+Future实现一千万个不重复整数的排序(Scala示例)
		目标 实现一千万个不重复整数的排序,可以一次性加载到 2G 的内存里. 本文适合于想要了解新语言 Scala 并发异步编程框架 Akka, Future 的筒鞋. 读完本文后,将了解如何综 ... 
- Akka系列(五):Java和Scala中的Future
		前言....... 随着CPU的核数的增加,异步编程模型在并发领域中的得到了越来越多的应用,由于Scala是一门函数式语言,天然的支持异步编程模型,今天主要来看一下Java和Scala中的Futrue ... 
- Scala教程之:Future和Promise
		文章目录 定义返回Future的方法 阻塞方式获取Future的值 非阻塞方式获取Future的值 Future链 flatmap VS map Future.sequence() VS Future ... 
- Scalaz(44)- concurrency :scalaz Future,尚不完整的多线程类型
		scala已经配备了自身的Future类.我们先举个例子来了解scala Future的具体操作: import scala.concurrent._ import ExecutionContext. ... 
- play for scala 实现SessionFilter 过滤未登录用户跳转到登录页面
		一.编写SessionFilter.scala代码 package filters import javax.inject.{Inject, Singleton} import akka.stream ... 
随机推荐
- Python虚拟机类机制之绑定方法和非绑定方法(七)
			Bound Method和Unbound Method 在Python中,当对作为属性的函数进行引用时,会有两种形式,一种称为Bound Method,这种形式是通过类的实例对象进行属性引用,而另一种 ... 
- Spring Boot 要点--启动类和热部署
			spring boot需要一个启动类 比如 package com.tianmaying; import org.springframework.boot.SpringApplication; imp ... 
- 安装 Windows Server 2012 Active Directory 只读域控制器 (RODC)(级别 200)
			安装 Windows Server 2012 Active Directory 只读域控制器 (RODC)(级别 200) 适用对象:Windows Server 2012 本主题介绍如何创建分步的 ... 
- WCF,WebServices,WebApi区别
			http://www.cnblogs.com/hetring/p/4493137.html 
- 【Linked List Cycle】cpp
			题目: Given a linked list, determine if it has a cycle in it. Follow up:Can you solve it without using ... 
- LeetCode——Problem1:two sum
			早就想刷LeetCode了,但一直在拖,新学期开学,开始刷算法. 我准备从Python和C++两种语言刷.一方面我想做机器学习,以后用Python会比较多,联系一下.另一方面C++或者C语言更接近底层 ... 
- jquery中attr和prop的区别介绍
			在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别?这些问题就出现了. 关于它们两个的区别,网上的答案很多.这里谈谈我的心得,我的心得很简单: ... 
- Callable、Future、FutureTask_笔记
			参考:http://blog.csdn.net/javazejian/article/details/50896505 1.Callable<V>接口 Runnable接口 public ... 
- Zabbix整合MegaCLI实现物理硬盘的自动发现和监控
			MegaCLI是LSI提供的用户空间管理RAID卡(LSI芯片)工具,适用于大多数的Dell服务器. MegaCLI介绍: http://zh.community.dell.com/techcente ... 
- 【bzoj4066】简单题  KD-tree
			题目描述 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命令 参数限制 内容 1 x y A 1<=x,y<=N,A是正整数 将格子x,y里的数 ... 
