Actor并发编程模型

Actor并发编程模型

Actor并发编程模型,是scala提供给程序员的一种与Java并发编程完全不一样的并发编程模型,是一种基于事件模型的并发机制。Actor并发编程模型是一种不共享数据,依赖消息传递的一种并发编程模式,有效避免资源争夺、死锁等情况。

Actor并发编程模型_第1张图片

Java并发编程对比Actor并发编程

Java内置线程模型 scala Actor模型
"共享数据-锁"模型 (share data and lock) share nothing
每个object有一个monitor,监视线程对共享数据的访问 不共享数据,Actor之间通过Message通讯
加锁代码使用synchronized标识
死锁问题
每个线程内部是顺序执行的 每个Actor内部是顺序执行的

一 Akka通信过程

学生创建一个ActorSystem
通过ActorSystem来创建一个ActorRef(老师的引用),并将消息发送给ActorRef
ActorRef将消息发送给Message Dispatcher(消息分发器)
Message Dispatcher将消息按照顺序保存到目标Actor的MailBox中
Message Dispatcher将MailBox放到一个线程中
MailBox按照顺序取出消息,最终将它递给TeacherActor接受的方法中

Actor并发编程模型_第2张图片

二 Actor程序运行流程

调用start()方法启动Actor
自动执行act()方法
向Actor发送消息
act方法执行完成后,程序会调用exit()方法

2.1 创建Actor

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()
  }
}

2.2 发送消息/接收消息

使用方式

发送消息

我们可以使用三种方式来发送消息:

发送异步消息,没有返回值
!? 发送同步消息,等待返回值
!! 发送异步消息,返回值是Future[Any]

要给actor1发送一个异步字符串消息,使用以下代码:

actor1 ! "你好!"

接收消息
Actor中使用receive方法来接收消息,需要给receive方法传入一个偏函数

创建两个Actor(ActorSender、ActorReceiver)
ActorSender发送一个异步字符串消息给ActorReceiver
ActorReceive接收到该消息后,打印出来

Actor并发编程模型_第3张图片

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)
  }
}

你可能感兴趣的:(Spark)