社区编辑申请
注册/登录
Scala Actor:多线程的基础学习
开发 后端
本文简单介绍了Scala Actor的核心机制。Scala里多线程的基础就是Actor,核心思想是用消息传递来进行线程间的信息共享和同步。

Scala Actor是Scala里多线程的基础,核心思想是用消息传递来进行线程间的信息共享和同步。

51CTO编辑推荐:Scala编程语言专题

Scala Actor线程模型可以这样理解:所有Actor共享一个线程池,总的线程个数可以配置,也可以根据CPU个数决定;当一个Actor启动之后,Scala分配一个线程给它使用,如果使用receive模型,这个线程就一直为该Actor所有,如果使用react模型,Scala执行完react方法后抛出异常,则该线程就可以被其它Actor使用。

下面看一些核心代码。

  1.  def start(): Actor = synchronized {  
  2.   // Reset various flags.  
  3.   //  
  4.   // Note that we do *not* reset `trapExit`. The reason is that  
  5.   // users should be able to set the field in the constructor  
  6.   // and before `act` is called.  
  7.  
  8.   exitReason = 'normal  
  9.   exiting = false 
  10.   shouldExit = false 
  11.  
  12.   scheduler execute {  
  13.     ActorGC.newActor(Actor.this)  
  14.     (new Reaction(Actor.this)).run()  
  15.   }  
  16.  
  17.   this 
  18. }  

其中Reaction实现Runnable接口,scheduler基本相当于是一个线程池,所以调用start方法之后会有一个线程来为该Actor服务。

使用receive模型。

  1. def receive[R](f: PartialFunction[Any, R]): R = {  
  2.  assert(Actor.self == this"receive from channel belonging to other actor")  
  3.  this.synchronized {  
  4.    if (shouldExit) exit() // links  
  5.    val qel = mailbox.extractFirst((m: Any) => f.isDefinedAt(m))  
  6.    if (null eq qel) {  
  7.      waitingFor = f.isDefinedAt  
  8.      isSuspended = true 
  9.      suspendActor()  
  10.    } else {  
  11.      received = Some(qel.msg)  
  12.      sessions = qel.session :: sessions  
  13.    }  
  14.    waitingFor = waitingForNone  
  15.    isSuspended = false 
  16.  }  
  17.  val result = f(received.get)  
  18.  sessions = sessions.tail  
  19.  result  
  20.   

如果当前mailbox里面没有可以处理的消息,调用suspendActor,该方法会调用wait;如果有消息,这调用PartialFunction进行处理。

使用react模型。

  1. def react(f: PartialFunction[Any, Unit]): Nothing = {  
  2.  assert(Actor.self == this"react on channel belonging to other actor")  
  3.  this.synchronized {  
  4.    if (shouldExit) exit() // links  
  5.    val qel = mailbox.extractFirst((m: Any) => f.isDefinedAt(m))  
  6.    if (null eq qel) {  
  7.      waitingFor = f.isDefinedAt  
  8.      continuation = f  
  9.      isDetached = true 
  10.    } else {  
  11.      sessions = List(qel.session)  
  12.      scheduleActor(f, qel.msg)  
  13.    }  
  14.    throw new SuspendActorException  
  15.  }  
  16.   

如果当前mailbox没有可以处理的消息,设置waitingFor和continuation,这两个变量会在接收到消息的时候使用;如果有消息,则调用scheduleActor,该方法会在线程池里选择一个新的线程来处理,具体的处理方法也是由PartialFunction决定。不管是哪条路径,react都会立即返回,或者说是立即抛出异常,结束该线程的执行,这样该线程就可以被其它Actor使用。

再来看看接收消息的处理代码。

  1. def send(msg: Any, replyTo: OutputChannel[Any]) = synchronized {  
  2.  if (waitingFor(msg)) {  
  3.    received = Some(msg)  
  4.  
  5.    if (isSuspended)  
  6.      sessions = replyTo :: sessions  
  7.    else 
  8.      sessions = List(replyTo)  
  9.  
  10.    waitingFor = waitingForNone  
  11.  
  12.    if (!onTimeout.isEmpty) {  
  13.      onTimeout.get.cancel()  
  14.      onTimeout = None  
  15.    }  
  16.  
  17.    if (isSuspended)  
  18.      resumeActor()  
  19.    else // assert continuation != null  
  20.      scheduler.execute(new Reaction(this, continuation, msg))  
  21.  } else {  
  22.    mailbox.append(msg, replyTo)  
  23.  }   

如果当前没有在等待消息或者接收到的消息不能处理,就丢到mailbox里去;相反,则进行消息的处理。这里对于receive模型和react模型就有了分支:如果isSuspended为true,表示是receive模型,并且线程在wait,就调用resumeActor,该方法会调用notify;否则就是react模型,同样在线程池里选择一个线程进行处理。

这样,相信大家对Scala Actor就有了一个基本的认识。

【相关阅读】

  1. Scala入门介绍:Hello World
  2. Scala初学者学习资料:main(String[])
  3. 影响Scala语言设计的因素列表
  4. 喜欢Scala编程的四个理由
  5. Scala融合面向对象和函数概念的方法
责任编辑:yangsai 来源: Shadow & Honnix
相关推荐

2022-06-12 06:48:34

2022-06-05 21:09:47

Python办公自动化

2022-06-13 12:43:13

Java模块

2022-06-16 17:02:49

微软智能云混合云Azure

2022-05-27 10:00:06

C++游戏引擎

2022-06-09 18:04:46

网络攻击网络安全

2022-06-22 09:19:55

HDC鸿蒙ADB命令

2022-06-16 15:42:16

攻击面管理ASM

2022-06-01 11:14:42

Java代码技巧

2022-06-16 07:32:38

VSCodePython插件

2022-06-01 17:47:24

运维监控系统

2022-06-28 14:47:43

数据中心服务器科技

2022-06-23 14:03:26

混合ITCIOIT管理工具

2022-06-28 10:03:56

CentOSLinux

2022-06-15 11:51:14

Vue3开发避坑

2022-06-24 11:14:00

美团开源

2022-06-09 09:27:16

前端行业生存

2022-06-23 09:22:57

Vue技巧前端

2022-06-06 10:20:59

CPUCPU 使用率CPU 负载

2022-06-25 21:22:30

编程Rust代码

同话题下的热门内容

源码探秘:Python 中对象是如何被调用的?吐血推荐17个提升开发效率的“轮子”超全!Python 中常见的配置文件写法Pandas 新手容易犯的六个错误Python 中的万能之王 Lambda 函数整理了100个Python精选库,建议收藏!Python进行数据可视化,你会用什么库来做呢?Spring MVC中@InitBinder注解是如何应用的?

编辑推荐

使用Kotlin做开发一个月后的感想面试官问你什么是消息队列?把这篇甩给他!五大自动化测试的Python框架图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS)2018年最流行的十大编程语言,其中包括你用的语言吗?
我收藏的内容
点赞
收藏

51CTO技术栈公众号