Akka Actor 提供了更高水平的并发和并行的抽象,Actor有如下的优点:
1.Actor可以看做是轻量级的线程,1GB RAM里面的Actor数目可以达到2.7百万(Actor运行在真正的线程上,可能有多个Actor共享一个线程)
2.错误冗余能力,被用来创建“自我恢复的系统”
3.本地透明性。Akka Actors可以跨越多个JVMS和服务器,使用纯消息发送的方式工作在分布式系统中。
1.预先准备
使用Actor需要先导入AKKA依赖,或者是手动添加相应的jar包
在intellij中添加AKKA
使用IDEA,创建SBT工程,在build.sbt中添加akka依赖:
resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/" libraryDependencies += "com.typesafe.akka" % "akka-actor_2.11" % "2.3.4"
2.Actor
actor是创建一个actor-based 系统的最小单元,就像是面向对象的编程模型(OOP)中的对象一样
你不能进入到一个actor中查看它的状态,但你可以向这个actor发送消息获取它的状态。
什么是actor,actor是一个封装了状态和行为的对象,每一个actor都通过message交流,从自己的mailbox中读取别的actor发送的消息(通过匹配)
ActorSystem 代表了一组actor.
注意:ActorSystem是重量级的对象,会创建1~N个线程,所以一个application一个ActorSystem
单Actor
在Scala中也可以使用Java线程,但是Actor模型更适合并行方法
Actor工作在分布式环境下(使用纯粹的消息发送)
只能发送消息,但是不能执行任何的方法或者是进入
一个Actor可能有parent,children,brother/sister兄弟姐妹...一级一级向下派,由下级完成
新建一个Actor:(通过extendsakka.actor.Actor)
在类中写一个接受方法receivemethod(该method应该被casestatement实施),允许actor根据收到的消息作出不同的回应。
例子:
class HelloActor(name:String) extends Actor{ //定义一个Actor
override def receive = { //Actor行为,通过定义一个接受方法(匹配表达式)
case "hello"=>println(s"hello back to you,$name")
case _ =>println(s"USB,$name")
}
}
object helloworld {
def main(args: Array[String]): Unit = {
val system = ActorSystem("Talk") //Talk系统名字 ActorSystem是一个共享配置的Actor组
val helloActor = system.actorOf(Props(new HelloActor("Ming")),name = "helloactor") //创建Actor " +helloactor"system.actorOf
helloActor ! "hello" //!方法进行消息的发送
helloActor ! "USB"
system.shutdown() //如果没有这句,应用不会终止,Actor和system依然会运行
}
}
多Actor
1.Actor也需要使用!方法来发送immutable消息。
2.当一个Actor从别的Actor接受到消息时,它也会接受到隐式的引用“sender”,Actor使用这个sender发送消息返回给原来的Actor
3.向一个Actor发送消息的一般语法:actorInstance! message
例子:
import akka.actor._
case object PingMessage
case object PongMessage
case object StartMessage
case object StopMessage //4个消息 被定义成了case object case匹配
class Ping(pong:ActorRef) extends Actor{
var count = 0
def incrementAndPrint={
count += 1
println("ping")
}
def receive= {
case StartMessage=>{
incrementAndPrint
pong ! PingMessage
}
case PingMessage=>{
incrementAndPrint
if(count > 99){
sender ! StopMessage
println("ping Stoped!")
context.stop(self) //context对于所有的actor隐式可用,用于停止actors
}
else{
sender ! PingMessage
}
}
case _=>{ println("pong got something unexpected")}
}
}
class Pong extends Actor{
def receive ={
case PingMessage=>{
println("pong")
sender ! PingMessage
}
case StopMessage=>{
println("pong stopped")
context.stop(self)
}
case _ =>println("Pong got something unexpected")
}
}
object PingPongTest {
def main(args: Array[String]): Unit = {
val system = ActorSystem("PingPongTest") // ActorSystem是重量级的对象,会创建1...N个线程,所以一个application一个ActorSystem。
val pong = system.actorOf(Props[Pong],name = "pong") //pong其实就是一个ActorRef actorOf返回一个ActorRef(保证消息不可变)
val ping = system.actorOf(Props(new Ping(pong)),name = "ping")
ping ! StartMessage //开始向Ping发送消息
}
}
在这个例子中,ping和pong不仅是ActorRef实例,也是sender变量