如何理解scala actor 例子的mailbox

我为什么想并且要学习 Scala
我的图书馆
我为什么想并且要学习 Scala
【数盟致力于成为最卓越的数据科学社区,聚焦于大数据、分析挖掘、数据可视化领域,业务范围:线下活动、在线课程、猎头服务、项目对接】作者:abbey&为什么学习函数式编程&在阅读DDD巨著《Patterns, Principles, and Practices of Domain-Driven Design》的过程中,Scott在第5章提到了使用函数式编程语言配合贫血模型去实践DDD的一种思路,这激发了我的无限遐想。在软件开发领域,我们已经拥有了许多的抽象方法论和大量的实现技术。但我个人认为,这一切归根结底,都是人类思维在软件开发领域的具体表达方式。而人类在认识和分析软件所要解决的业务领域问题时,思考的内容不外乎由两个部分组成:『业务流程』与『业务规则』。前者,回答了业务活动中先做什么后做什么的问题;后者,则回答了遇到什么情况时应该怎么做的问题。两者结合后,得到我们需要的业务结果,或者叫作“实现业务目标”。&再想想目前学习和掌握的面向对象的一系列方法,又是如何将上述思维结果映射到软件中去的呢?我认为是这样的:&对于业务流程,我们将其表达为若干对象之间的合作,比如UML里序列图的对象与消息,进而具化为具体的类及其职责,比如类及其若干业务方法。对于业务规则,我们将其表达为若干的判断逻辑,比如UML流程图里的判断分支,进而具化为业务方法里的if-else语句,或者再复杂一点,表达为工厂、策略等设计模式的实际运用。&然后,我认为,对于复杂业务规则的梳理,可以象数学归纳法一样进行演绎:假设一个函数y=f(x),给定x的定义域,确定y的值域。特别是在排列组合等方面的一些问题,也经常采用递归的方式来解决。所以,从这个角度讲,函数式编程更贴近人类思维习惯,所以让我自然而然地把目光转向了它。&为什么选择Scala&在选择具体的函数式编程语言时,我首先想到的是它最好是同时能支持面向对象编程的。因为即便LISP作为函数式编程语言的先祖,诞生已长达半个世纪,但单纯的函数式编程语言与面向对象编程语言相比,在抽象领域概念、组合系统模块、实现信息隐蔽等方面存在一定的差距,所以一直没有成为软件开发的主流。&信息隐蔽原理:在西安电子科大蔡希尧与陈平老师于1993年合作出版的《面向对象技术》一书中是这样描述的:把需求和求解的方法分离;把相关信息——数据结构和算法,集中在一个模块之中,和其他模块隔离,它们不能随便访问这个模块内部的信息。&其次,由于我的语言路线是从Pascal → C → C → C#,所以我希望能选择一种风格近似于C、强类型的函数式编程语言。在比较了F#、R、ErLang等几种常见的函数式编程语言之后,我最终选择了Scala。&Scala有何优势&注:以下内容,节选翻译或参考自《Programming in Scala》第1章、第3章,《Programming Scala》第6章,不算完整意义上的个人心得。&函数式编程的优势&纯的函数是没有副作用的。无论何时何地,对于一个函数y=f(x),给定x必定得到y,不会因此产生二义结果。因此无论对于代码测试还是并发,由于给定输入必定得到预期输出,而不受其他因素干扰,所以能有效减少Bug产生。在函数式编程里,大量使用immutable的值。这意味着函数运算的结果总会创建一个新的实例,避免了通常并发环境下为防止数据共享冲突而采取的保护机制。尽管这需要额外的Copy操作,但Scala针对性地提供了高效的Copy实现,以及延迟计算等弥补机制。函数是一等公民。函数作为表达式的一部分,可以借由函数之间的嵌套、组合,实现复杂的判断逻辑。&Scala语言本身的优势&Scala是面向对象与函数式编程的混合语言,所以能有效结合二者的优点。Scala属于Java生态圈,可以在JVM平台上与Java一起编译运行,所以许多Java的框架、工具都可以直接应用于Scala语言编写的项目。Scala视一切数据类型皆为对象,且支持闭包、lambda、by-name参数等特性,语法简洁明快。Scala使用Actor作为并发模型,与Akka框架自然契合。这是一种区别于传统的、基于数据共享、以锁为主要机制的并发模型,其特点在于以Actor为基本单位、没有数据共享、基于消息传递实现Actor之间的协作,因此可以有效避免死锁、减少竞争。最后,如果有朝一日要转向大数据领域,有Spark这样的大型框架作为支撑。知乎:与 Hadoop 对比,如何看待 Spark 技术?&Scala对实践DDD有何意义&说了那么多,我的根本目的还是要将Scala作为实现DDD的主要武器。那么试想一下,Scala在我们实现DDD的过程中能有哪些帮助呢?我暂且胡侃乱诌如下:表示值对象、领域事件等元素更直观。值对象、领域事件在DDD里都应该是immutable的,以往多采取POCO形式表示,现在改用Scala里的val以及case class表示,在语法层面就直观地表明是不可修改的。在类的方法层面实现CQRS时有语法支持。用Scala里的Function(返回类型为非Unit)对应CQRS里的Query,保证类的方法没有副作用;用Procedure(返回类型为Unit)对应CQRS里的Command,明确表明这一类方法会产生修改状态等副作用。这同样从语法层面就能对二者进行明确区分。模式匹配丰富了函数操作。除了正则表达式,Scala形式多样的模式匹配语法,为提取数据、完成数据分组聚合等运算、实现逻辑判断提供了强大支持。比如定义def sum_count(ints:Seq[Int) = (ints.sum, ints.size)这样一个函数后,我们可以这样调用,以得到一个1至6的整数序列的整数值合计,及该序列的尺寸: val(sum, count) = sum_count(List(1, 2, 3, 4, 5, 6))。为实现DSL提供有力支持。Scala自带有解析框架,加上灵活的函数语法支持,要自己实现一套DSL及其相应的语法解析器将不再困难。比如在配置文件里这样的一条配置语句,表示退休条件为年龄达到60周岁或者工龄届满30年:retire = (Age &= 60) || (ServiceLength &= 30)。以往的方式是自己写一个语法解析器,把这条文本转换成相应的Specification对象,然后扔给聚合去使用。现在有了Scala的帮助,就使编写语法解析器这一环节的工作量大大减少。合理的高阶函数设计,使规则编写得到简化。比如打折规则、费用报销规则,以往可能需要若干层的if-else嵌套,现在则将通过高阶函数得到大幅简化。对此,我强烈推荐刘光聪先生的视频Refactoring to Functions,你会在刘先生的重构过程中发现高阶函数的强大。Actor为高效并发打下基础。Actor内部完全自治,自带用于存储消息的mailbox,与其他Actor只能通过消息进行交互,每个Actor都是并发的一个基本单位。这些特点,非常适合于采取Event Sourcing方式实现的DDD。每个聚合都好比一个Actor,在聚合内部始终保持数据的强一致性,而在聚合之间交互的领域事件则好比Actor之间的消息,聚合之间借由领域事件和Saga保证数据的最终一致性。Trait成为AOP利器。Trait是Scala的另一大特色,它就象AOP织入一样,能动态地给某个类型注入方法或者结构。比如配合类Circuit和with后面那4个Trait的定义,val circuit = new Circuit with Adders with Multiplexers with Flipflops with MultiCoreProcessors这样就创建了一个带有加法器、乘法器、触发器和多核处理器的元件。隐式实现为类型扩展提供支持。对应C#里的静态扩展方法,Scala通过implicit为实现数据类型的方法扩展提供了便捷,成为Trait之外的另一个功能扩展手段。能降低常见BDD框架的学习成本。尽管这一点可能比较牵强,但我正在努力摸索如何将BDD与DDD结合,而常见的Cucumber、Spock等一些BDD框架,其语法与Scala比较相近,所以我才有如此一说。&有哪些Scala学习资料&以下是我目前主要的学习资料,并衷心欢迎各位留言补充。&书籍Programming in Scala:由Scala语言的设计师Martin Odersky编写,循序渐进,配合了大量实例,入门必读吧。Programming Scala:视角与上面那本有点不一样,没有Scala语言基础会感觉很困难,适合掌握了基本语法后温故而知新。&在线文档与视频Scala 官方文档:Scala的官网,作为寻找资料的出发点是不错的。Scala 课堂:中文版的Scala基本语法在线课堂。Scala Synatax Primer:由Jim McBeath整理的Scala语法概要,可以当字典用。The Neophyte’s Guide to Scala:很出名的一个Scala入门指南,以Scala中的提取器Extractor作为实例开始。Scala 初学指南:这是上面那本指南的中译本。Effective Scala:中文版的Scala高效编程SBT中文入门指南:Scala Build Tool&社区Scala 中文社区:不算活跃,原因你懂的。Scala User:Scala入门者聚集地,没有Stack Overflow那么严格,但也需要点爬墙的身手。&SDK及IDEJava SE:先装这个Scala SDK:再装这个SBT:然后装这个IntelliJ IDEA:最后装这个,就能比较方便地开始Scala编程了&写在最后&最近读的书很多也很杂,DDD、BDD、Scala、Cucumber以及Java基础等等都有涉及,真恨不得一口吃成个大胖子。由于时间和精力有限,所以现在知识消化很成问题,迟迟没有进入学以致用的环节,只能先这样纸上谈兵了,好歹先把自己在学习过程中的一些思考、看到的好东西先记载下来,以备将来之需。原文链接:/topics/134?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io&
TA的最新馆藏[转]&[转]&1867人阅读
Language(48)
在了解了Scala的一些基本特性之后,看到了它的线程实现:Actor。笔者不知道这么叫是否合适,因为Actor的目的似乎专注于在实体之间使用消息传递来协作。翻了一下它的原型定义如下:
abstract class Actor extends Thread with MailBox{
def act() : Unit
override def run(): Unit = act()
def !(msg: Any) = send(msg)
从这个版本的源码(&=Scala 2.7)中可以看出,Actor除了代表线程类之外还引入了MailBox,本来我们都知道继承java.lang.Thread只会要求重写run()方法,不会有别的改变,Scala使用act()来代替了使用run()的习惯,由于混入了MailBox使得Scala的Actor具有了receive和receiveWith等新的方法,从而完成消息传递的协作。(但笔者最近在新的Scala版本中发现这一切都有了重大改变,Actor不再混入MailBox,整个Actor只包含了伴生对象object
Actor和抽象接口trait Actor的定义,看起来线程实现的角色更加简洁明了。receive和receiveWithIn被同时直接加入为伴生对象Actor和trait Actor中。)
这里不深入讨论Actor的特点,先通过一个小例子,来看Actor是如何工作的:
import scala.actors.Actor, java.util._
abstract class AuctionMessage
case class Offer(bid: Int, client: Actor) extends AuctionMessage
case class Inquire(client: Actor) extends AuctionMessage
case object TIMEOUT
abstract class AuctionReply
case class Status(asked: Int, expire: Date) extends AuctionReply
case object BestOffer extends AuctionReply
case class BeatenOffer(maxBid: Int) extends AuctionReply
case class AuctionConcluded(seller: Actor, client: Actor) extends AuctionReply
case object AuctionFailed extends AuctionReply
case object AuctionOver extends AuctionReply
* Before finally stopping, it stays active for another period determined by the
* timeToShutdown constant and replies to further offers that the auction is closed
class Auction (seller: Actor, minBid: Int, closing: Date) extends Actor{
// 60 minutes to shut down the auction
val timeToShutdown = 3600000
// minimum bid for each offer
val bidIncrement = 10
def act(){
var maxBid = minBid - bidIncrement
var maxBidder: Actor = null
var running = true
while(running){
//receiveWithin: just span a period of time for mailbox messages then stopped
receiveWithin ((closing.getTime() - new Date().getTime())){
case Offer(bid, client) =&
if(bid &= maxBid + bidIncrement){
//beat successfully, notify the current maxBidder, then replace it
if(maxBid &= minBid) maxBidder ! BeatenOffer(bid)
//reply to client the current offer peak value
maxBid = maxBidder = client ! BestOffer
//beat failed, return the current max bid value to offer client
client ! BeatenOffer(maxBid)
case Inquire(client) =&
// query the max bid and closing time
client ! Status(maxBid, closing)
case TIMEOUT =&
//auction done
if(maxBid &= minBid){
val reply = AuctionConcluded(seller, maxBidder)
maxBidder ! seller ! reply
//no one get the auction, notify seller
seller ! AuctionFailed
//for further offer message, tell them over
receiveWithin(timeToShutdown){
case Offer(_, client) =& client ! AuctionOver
case TIMEOUT =& running = false
这是一个拍卖通信的例子,在while循环里Auction能分辨请求消息的种类然后做合适的处理,当发生超时事件,开始进行整个结束流程。
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:519001次
积分:6565
积分:6565
排名:第3225名
原创:119篇
转载:74篇
评论:138条
(2)(3)(2)(4)(1)(2)(2)(1)(2)(1)(1)(1)(1)(6)(2)(7)(3)(3)(3)(1)(7)(6)(5)(4)(3)(1)(1)(2)(1)(2)(1)(2)(2)(3)(2)(6)(3)(7)(6)(5)(2)(5)(10)(6)(3)(2)(5)(5)(8)(6)(2)(5)(4)(4)(12)Scala学习笔记7 (actor)
Scala学习笔记7 (actor)
发布时间: 5:16:03
编辑:www.fx114.net
本篇文章主要介绍了"Scala学习笔记7 (actor)",主要涉及到Scala学习笔记7 (actor)方面的内容,对于Scala学习笔记7 (actor)感兴趣的同学可以参考一下。
7.&&&actor
http://www.scala-lang.org/docu/files/actors-api/actors_api_guide.html#
Scala中处理并发,有很多选择:
l&&actor消息模型,类似Erlang,首选,Lift和akka也实现了自己的actor模型。
l&&Thread、Runnable
l&&java.util.concurennt
l&&3rd并发框架如Netty,Mina
7.1.&&&&&actor模型
Java内置线程模型
Scala actor模型
“共享数据-锁”模型(share data and lock)
share nothing
每个object有一个monitor,监视多线程对共享数据的访问
不共享数据,actor之间通过message通讯
加锁的代码段用synchronized标识
每个线程内部是顺序执行的
每个actor内部是顺序执行的
7.2.&&&&&多核计算
对比如下的算法:
def perfect(n:Int) =
n==(1 until n filter (n%_==0) sum)
//&串行计算
n to n+10 foreach (i=&println(perfect(i)))
def perfect(n:Int) =
n==(1 until n filter (n%_==0) sum)
//&并行计算
class T1(n:Int) extends Thread {
& override def run(){println(perfect(n))}}
n to n+10 foreach (i=&new T1(i).start)
耗时:8297
耗时:5134
单线程串行计算,不能很好发挥多核优势
多线程并行计算,平均分配到多核,更快
上面是Java的写法,也可以用Scala的actor写法:
Scala写法1:
import actors.Actor,actors.Actor._
class A1 extends Actor {
def act { react { case n:Int=&println(perfect(n)) }}}
n to n+10 foreach (i=&{ (new A1).start ! i})
Scala写法2:
val aa = Array.fill(11)(actor { react { case n:Int=&println(perfect(n)) }})
n to n+10 foreach (i=&aa(i-n) ! i)
n to n+10 foreach (i=&&actor { react { case n:Int=&println(perfect(n)) }}&! i)
7.3.&&&&&Actor用法
Scala会建立一个线程池共所有Actor来使用。receive模型是Actor从池中取一个线程一直使用;react模型是Actor从池中取一个线程用完给其他Actor用
实现方式1:
import&scala.actors._
object&Actor1&extends&Actor&{
//&或者class
//&实现线程
{ react { case _ =&println(&ok&); exit} }
//发送消息:
Actor1.start ! 1001 //&必须调用start
实现方式2:
import&scala.actors.Actor._
val&a2&=&actor&{&react
{ case _ =&println(&ok&) }&} //&马上启动
//发送消息:
a2 ! &message& //&不必调用start
发送异步消息,没有返回值。
发送同步消息,等待返回值。(会阻塞发送消息语句所在的线程)
发送异步消息,返回值是&Future[Any]。
不带参数。查看&mailbox&中的下一条消息。
7.4.&&&&&方式1:接受receive
特点:要反复处理消息,receive外层用while(..)
import actors.Actor, actors.Actor._
val a1 =&Actor.actor&{
var&work&=&true
while(work)
receive&{&//&接受消息,&或者用receiveWith(1000)
case&msg:String&=&&println(&a1:
&&+&msg)
case&x:Int&=&&work&=&&println(&a1
stop: &&+&x)
a1&!&&hello& // &a1: hello&
a1&!&&world& // &a1: world&
a1&!&-1 // &a1 stop: -1&
a1&!&&no response :(&
7.5.&&&&&方式2:接受react,
l&&从不返回
l&&要反复执行消息处理,react外层用loop,不能用while(..);
l&&通过复用线程,比receive更高效,应尽可能使用react
import actors.Actor, Actor._
val a1 =&Actor.actor&{
&&&&&&&&case&x:Int =& println(&a1
stop: &&+ x)
&&&&&&&&case&msg:String =& println(&a1:
&&+ msg);&act()
a1&!&&hello& // &a1: hello&
a1&!&&world& // &a1: world&
a1&!&-1 // &a1 stop: -1&
a1&!&&no response :(&
如果不用退出的线程,可使用loop改写如下:
val a1 =&Actor.actor&{
case&x:Int&=&&println(&a1
stop: &&+&x);&exit()
&&& &&&&case&msg:String =& println(&a1:
&&+ msg)
7.6.&&&&&REPL接受消息
scala& self ! &hello&
scala& self.receive { case x =& x }
scala& self.receiveWithin(1000) { case x =& x }
7.7.&&&&&actor最佳实践
7.7.1.&&不阻塞actor
actor不应由于处理某条消息而阻塞,可以调用helper-actor处理耗时操作(helper actor虽然是阻塞的,但由于不接受消息所以没问题),以便actor接着处理下一条消息
-----------------------------------------
import&actors._, actors.Actor._
val&time = 1000
&&//&(1)原来阻塞的程序
&&val&mainActor1 = actor {
&&& loop { react {
&&&&&&&&case&n:&Int&=&&Thread.sleep(time)
&&&&&&& &&&&&&&&&&&&&&&&&println(n)
&&&&&&&&case&s =& println(s) } }
& 1 to 5 foreach { mainActor1 ! _ }&// 5秒钟后打印完数字
&&//&(2)改写由helper
actor去阻塞的程序
&&val&mainActor2: Actor = actor {
&&& loop { react {
&&&&&&&&case&n:&Int&=&&actor
{ Thread.sleep(time); mainActor2 !&&wakeup&&}
&&&&&&& &&&&&&&&&&&&&&&&println(n)
&&&&&&&&case&s =& println(s) } }
& 1 to 5 foreach { mainActor2 ! _ }&//&马上打印数字;
1秒钟后打印5个wakeup
-----------------------------------------
7.7.2.&&actor之间用且仅用消息来通讯
actor模型让我们写多线程程序时只用关注各个独立的单线程程序(actor),他们之间通过消息来通讯。例如,如果BadActor中有一个GoodActor的引用:
class BadActor(a:GoodActor) extends Actor {...}
那在BadActor中即可以通过该引用来直接调用GoodActor的方法,也可以通过“!”来传递消息。选择后者!因为一旦BadActor通过引用读取GoodActor实例的私有数据,而这些数据可能正被其他线程改写值,结果就避免不了“共享数据-锁”模型中的麻烦事:即必须保证BadActor线程读取GoodActor的私有数据时,GoodActor线程在这块成为“共享数据”的操作上加锁。GoodActor只要有了共享数据,就必须来加锁防范竞用冲突和死锁,你又得从actor模型退回到“共享数据-锁”模型(注:actor对消息是顺序处理的,本来不用考虑共享数据)。
7.7.3.&&采用不可变消息
Scala的actor模型让每个actor的act方法内部接近于单线程环境,你不用当心act方法里面的操作是否线程安全。在act方法中你可以尽情使用非同步、可变对象,因为每个act方法被有效限制在单个线程中,这也是actor模型被称为“share-nothing”&模型(零共享模型)的原因,其数据的作用范围被限制在单个线程中。不过一旦对象内的数据被用于多个actor之间进行消息传递。这时你就必须考虑消息对象是否线程安全。
保证消息对象线程安全的最好方法就是保证只使用不可变对象作为消息对象。消息类中只定义val字段,且只能指向不可变对象。定义这种不可变消息类的简单方法就是使用case
class,&并保证其所有的val字段都是不可变的。Scala
API中提供了很多不可变对象可用,例如基本类型、String、Tuple、List,不可变Set、不可变Map等。
如果你发现确实需要把一个可变对象obj1发送给其他actor,也因该是发送一份拷贝对象obj1.clone过去,而不是把obj1直接发过去。例如,数据对象Array是可变且未做同步的,所以Array只应该由一个actor同时存取,如果需要发送数组arr,就发送arr.clone(arr中的元素也应该是不可变对象),或者直接发送一个不可变对象arr.toList更好。
总结:大部分时候使用不可变对象很方便,不可变对象是并行系统的曙光,它们是易使用、低风险的线程安全对象。当你将来要设计一个和并行相关的程序时,无论是否使用actor,都应该尽量使用不可变的数据结构。
7.7.4.&&让消息自说明
对每一种消息创建一个对应的case class,而不是使用上面的tuple数据结构。虽然这种包装在很多情况下并非必须,但该做法能使actor程序易于理解,例如:
//&不易理解,因为传递的是个一般的字符串,很难指出那个actor来响应这个消息
lookerUpper ! (&www.scala-lang.org&, self)
//&改为如下,则指出只有react能处理LoopupIP的actor来处理:
case&class&LookupIP(hostname: String, requester: Actor)
lookerUpper ! LookupIP(&www.scala-lang.org&, self)
7.8.&&&&&不同jvm间的消息访问
服务器端:
object&ActorServer&extends&Application&{
&&&&import&actors.Actor,&actors.Actor._,&actors.remote.RemoteActor
&&&&Actor.actor&{&//&创建并启动一个&actor
&&&&&&//&当前&actor&监听的端口:&3000
&&&&&&RemoteActor.alive(3000)
&&&&&&//&在&3000&端口注册本&actor,取名为&server1。
&&&& &//&第一个参数为&actor&的标识,它以单引号开头,是&Scala&中的&Symbol&量,
&&&&&&// Symbol&量和字符串相似,但&Symbol&相等是基于字符串比较的。
&&&&&&// self&指代当前&actor&(注意此处不能用&this)
&&&&&&RemoteActor.register('server1,&Actor.self)
&&&&&&//&收到消息后的响应
&&&&&&loop&{
&&&&&&&&Actor.react&{case&msg&=&
&&&&& &&&&println(&server1
get: &&+&msg)
object&ActorClient&extends&Application&{&
&&&&import&actors.Actor,&actors.remote.Node,&actors.remote.RemoteActor&
&&&&Actor.actor&{&
&&&&&&//&取得一个节点(ip:port&唯一标识一个节点)&
&&&&&&// Node&是个&case
class,所以不需要&new&
&&&&&&val&node&=&Node(&127.0.0.1&,
&&&&&&//&取得节点对应的&actor&代理对象&
&&&&&&val&remoteActor&=&RemoteActor.select(node,&'server1)&
&&&&&&//&现在&remoteActor&就和普通的&actor&一样,可以向它发送消息了!&
&&&&&&println(&--
begin to send message&)
&&&&&&remoteActor&!&&ActorClient的消息&&
&&&&&&println(&--
7.9.&&&&&STM
/scala-stm/
a lightweight&Software Transactional Memory&for Scala, inspired by the STMs in Haskell and Clojure.
Cheat-Sheet:
import scala.concurrent.stm._
val x = Ref(0) // allocate a Ref[Int]
val y = Ref.make[String]() // type-specific default
val z = x.single // Ref.View[Int]
atomic { implicit txn =&
& val i = x() // read
& y() = &x was & + i // write
& val eq = atomic { implicit txn =& // nested atomic
&&& x() == z() // both Ref and Ref.View can be used inside atomic
& assert(eq)
& y.set(y.get + &, long-form access&)
// only Ref.View can be used outside atomic
println(&y was '& + y.single() + &'&)
println(&z was & + z())
atomic { implicit txn =&
& y() = y() + &, first alternative&
& if (x getWith { _ & 0 }) // read via a function
retry // try alternatives or block
} orAtomic { implicit txn =&
& y() = y() + &, second alternative&
val prev = z.swap(10) // atomic swap
val success = z.compareAndSet(10, 11) // atomic compare-and-set
z.transform { _ max 20 } // atomic transformation
val pre = y.single.getAndTransform { _.toUpperCase }
val post = y.single.transformAndGet { _.filterNot { _ == ' ' } }
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:您所在的位置: &
从Java走进Scala:一步步教你使用Scala Actor(1)
从Java走进Scala:一步步教你使用Scala Actor(1)
Ted Neward
“actor” 实现在称为 actor 的执行实体之间使用消息传递进行协作,而Scala Actor是Scala并发编程中最重要的一个机制。本文生趣的介绍了如何使用Scala Actor。
中,我讨论了构建并发代码的重要性(无论是否是 Scala 代码),还讨论了在编写并发代码时开发人员面对的一些问题,包括不要锁住太多东西、不要锁住太少东西、避免死锁、避免生成太多线程等等。
51CTO编辑推荐:
这些理论问题太沉闷了。为了避免读者觉得失望,我与您一起研究了 Scala 的一些并发构造,首先是在 Scala 中直接使用 Java 语言的并发库的基本方法,然后讨论 Scala API 中的 MailBox 类型。尽管这两种方法都是可行的,但是它们并不是 Scala 实现并发性的主要机制。
真正提供并发性的是 Scala 的 actor。
什么是 “actor”?
“actor” 实现在称为 actor 的执行实体之间使用消息传递进行协作(注意,这里有意避免使用 “进程”、“线程” 或 “机器” 等词汇)。尽管它听起来与 RPC 机制有点儿相似,但是它们是有区别的。RPC 调用(比如 Java RMI 调用)会在调用者端阻塞,直到服务器端完成处理并发送回某种响应(返回值或异常),而消息传递方法不会阻塞调用者,因此可以巧妙地避免死锁。
仅仅传递消息并不能避免错误的并发代码的所有问题。另外,这种方法还有助于使用 “不共享任何东西” 编程风格,也就是说不同的 actor 并不访问共享的数据结构(这有助于促进封装 actor,无论 actor 是 JVM 本地的,还是位于其他地方) ― 这样就完全不需要同步了。毕竟,如果不共享任何东西,并发执行就不涉及任何需要同步的东西。
这不算是对 actor 模型的正规描述,而且毫无疑问,具有更正规的计算机科学背景的人会找到各种更严谨的描述方法,能够描述 actor 的所有细节。但是对于本文来说,这个描述已经够了。在网上可以找到更详细更正规的描述,还有一些学术文章详细讨论了 actor 背后的概念(请您自己决定是否要深入学习这些概念)。现在,我们来看看 Scala actors API。
内容导航&第 1 页: &第 2 页: &第 3 页: &第 4 页: &第 5 页:
关于的更多文章
AngularJS是很多Web开发人员在打造单页面应用程序时的首选创建方
随着云计算、物联网、大数据、移动互联网的大发展,你应该知道这些。
讲师: 35人学习过讲师: 17人学习过讲师: 252人学习过
进入12月份,一年的日子到头了。年末总结什么的也都开
Jquery是继prototype之后又一个优秀的Javascript框架
又到周末了。昨天是感恩节,小编也是听同事说起,才想
本书依据最新版《网络管理员考试大纲》的考核要求,深入研究了历年网络管理员考试试题的命题风格和试题结构,对考查的知识点进行
51CTO旗下网站

我要回帖

更多关于 scala actor 包 的文章

 

随机推荐