Actor并发编程模型,是scala提供给程序员的一种与Java并发编程完全不一样的并发编程模型,是一种基于事件模型的并发机制。Actor并发编程模型是一种不共享数据,依赖消息传递的一种并发编程模式,有效避免资源争夺、死锁等情况。
Java内置线程模型 | scala Actor模型 |
---|---|
"共享数据-锁"模型 (share data and lock) | share nothing |
每个object有一个monitor,监视线程对共享数据的访问 | 不共享数据,Actor之间通过Message通讯 |
加锁代码使用synchronized标识 | |
死锁问题 | |
每个线程内部是顺序执行的 | 每个Actor内部是顺序执行的 |
学生创建一个ActorSystem
通过ActorSystem来创建一个ActorRef(老师的引用),并将消息发送给ActorRef
ActorRef将消息发送给Message Dispatcher(消息分发器)
Message Dispatcher将消息按照顺序保存到目标Actor的MailBox中
Message Dispatcher将MailBox放到一个线程中
MailBox按照顺序取出消息,最终将它递给TeacherActor接受的方法中
调用start()方法启动Actor
自动执行act()方法
向Actor发送消息
act方法执行完成后,程序会调用exit()方法
package com.xu
import scala.actors.Actor
import scala.io.StdIn
object ScalaTest {
class Actor1 extends Actor {
override def act(): Unit = {
(1 to 10).foreach(println(_))
}
}
object Actor2 extends Actor {
override def act(): Unit = {
(10 to 20).foreach(println(_))
}
}
def main(args: Array[String]): Unit = {
new Actor1().start()
Actor2.start()
}
}
发送消息
我们可以使用三种方式来发送消息:
! | 发送异步消息,没有返回值 |
---|---|
!? | 发送同步消息,等待返回值 |
!! | 发送异步消息,返回值是Future[Any] |
要给actor1发送一个异步字符串消息,使用以下代码:
actor1 ! "你好!"
接收消息
Actor中使用receive方法来接收消息,需要给receive方法传入一个偏函数
创建两个Actor(ActorSender、ActorReceiver)
ActorSender发送一个异步字符串消息给ActorReceiver
ActorReceive接收到该消息后,打印出来
package com.xu
import java.util.concurrent.TimeUnit
import scala.actors.Actor
object ScalaTest {
object ActorReceiver extends Actor {
override def act(): Unit = {
while (true) {
receive {
case msg:String => println("接收到消息:" + msg)
}
}
}
}
object ActorSender extends Actor {
override def act(): Unit = {
while (true) {
ActorReceiver ! "hello!!!!!"
TimeUnit.SECONDS.sleep(3)
}
}
}
def main(args: Array[String]): Unit = {
ActorReceiver.start()
ActorSender.start()
}
}
创建一个MsgActor,并向它发送一个同步消息,该消息包含两个字段(id、message)
MsgActor回复一个消息,该消息包含两个字段(message、name)
打印回复消息
使用!?来发送同步消息
在Actor的act方法中,可以使用sender获取发送者的Actor引用
package com.xu
import scala.actors.Actor
object ScalaTest {
case class Message(id:Int, msg:String)
case class ReplyMessage(msg:String, name:String)
object MsgActor extends Actor {
override def act(): Unit = {
loop {
react {
case Message(id, msg) => {
println(s"接受到的消息:${id}/${msg}")
sender !ReplyMessage("不太好", "Tomjjjj")
}
}
}
}
}
def main(args: Array[String]): Unit = {
MsgActor.start()
val replyMessage:Any = MsgActor !? Message(1, "你好")
println("回复消息:" + replyMessage.asInstanceOf[ReplyMessage])
}
}
创建一个MsgActor,并向它发送一个异步无返回消息,该消息包含两个字段(message, company)
使用!发送异步无返回消息
package com.xu
import scala.actors.Actor
object ScalaTest {
case class Message(msg:String, name:String)
object MsgActor extends Actor {
override def act(): Unit = {
loop{
react {
case Message(msg, name) =>
println(s"接受到的消息为:${msg}/${name}")
}
}
}
}
def main(args: Array[String]): Unit = {
MsgActor.start()
MsgActor !Message("哈哈", "heiehe")
}
}
创建一个MsgActor,并向它发送一个异步有返回消息,该消息包含两个字段(id、message)
MsgActor回复一个消息,该消息包含两个字段(message、name)
打印回复消息
使用!!发送异步有返回消息
发送后,返回类型为Future[Any]的对象
Future表示异步返回数据的封装,虽获取到Future的返回值,但不一定有值,可能在将来某一时刻才会返回消息
Future的isSet()可检查是否已经收到返回消息,apply()方法可获取返回数据
package com.xu
import scala.actors.{Actor, Future}
object ScalaTest {
case class Message(msg:String, name:String)
case class ReplyMessage(mm:String, nn:String)
object MsgActor extends Actor {
override def act(): Unit = {
loop{
react {
case Message(msg, name) =>
println(s"接受到的消息为:${msg}/${name}")
sender ! ReplyMessage("收到!!", "Jim")
}
}
}
}
def main(args: Array[String]): Unit = {
MsgActor.start()
val aaa: Future[Any] = MsgActor !! Message("hhh","你好")
while(!aaa.isSet) {}
val replyMessage = aaa.apply().asInstanceOf[ReplyMessage]
println(replyMessage)
}
}