Scala编程基础(十一)-- 编程实战(利用Akka的actor编程模型,实现2个进程间的通信)

利用Akka的actor编程模型,实现2个进程间的通信。

1.架构图

2.重要类介绍

ActorSystem在Akka中,ActorSystem是一个重量级的结构,他需要分配多个线程,所以在实际应用中,ActorSystem通常是一个单例对象,我们可以使用这个ActorSystem创建很多Actor。

注意

(1)、ActorSystem是一个进程中的老大,它负责创建和监督actor

(2)、ActorSystem是一个单例对象

(3)、actor负责通信

3.Actor

在Akka中,Actor负责通信,在Actor中有一些重要的生命周期方法。

1preStart()方法:该方法在Actor对象构造方法执行后执行,整个Actor生命周期中仅执行一次。

2receive()方法:该方法在ActorpreStart方法执行完成后执行,用于接收消息,会被反复执行。

4.实现步骤

5.具体代码

(1)master端代码

import akka.actor.{Actor, ActorSystem, Props}
import com.typesafe.config.ConfigFactory

//todo:利用akka中的actor模型来实现2个进程间的通信----master端
class Master extends Actor{

  //不在任何方法中的代码,称为构造代码
  //master构造代码先执行
  println("Master constructor invoked")

  //构造代码后执行,类似一个初始化的方法
  override def preStart(): Unit = {
    println("preStart method invoked")
  }

  //receive方法会在preStart方法执行后被调用,在这里表示不断的接收消息
  override def receive: Receive = {
    case "start" =>{
      println("a client connected")
    }
    case "register" =>{
      println("a client register")

      //master 反馈注册成功的信息给worker  sender()表示worker的引用
      sender() ! "success"
    }
  }

}

object Master{

  def main(args: Array[String]): Unit = {

    //定义master的ip地址和端口 参数:127.0.0.1 8888
    val host = args(0)
    val port = args(1)

    //准备配置信息 shift+英文上引号 3次
    val configStr: String =
      s"""
         |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
         |akka.remote.netty.tcp.hostname = "$host"
         |akka.remote.netty.tcp.port = "$port"
      """.stripMargin

    //构建一个config对象
    val config = ConfigFactory.parseString(configStr)

    //1.创建ActorSystem老大,它负责创建和监督子Actor
    val masterActorSystem = ActorSystem("masterActorSystem",config)

    //2.基于masterActorSystem 来创建master actor
    val masterActor = masterActorSystem.actorOf(Props(new Master),"masterActor")

    //3.测试 向master actor发送一个消息
    masterActor ! "start"

  }

}

(2)worker端代码

import akka.actor.{Actor, ActorRef, ActorSelection, ActorSystem, Props}
import com.typesafe.config.ConfigFactory

//todo:利用akka来实现actor模型来实现2个进程间的通信 --worker端
class Worker extends Actor{

  //构造代码先运行
  println("Worker constructor invoked")

  //preStart方法会在构造代码执行后被调用 只会被执行一次
  override def preStart() : Unit = {
    println("preStart method invoked")

    //获取到master的引用
    //通过ActorContext上下文对象,调用actorSelection从已存在actor中找到目标actor 方法中需要一个字符串
    //这个字符串包括了:1.通信协议 2.master的ip 3.master端口
    //4.master actor的名称 5.创建master actor的老大 ActorSystem 6.actor层级关系
    val master: ActorSelection = context.actorSelection(
      "akka.tcp://masterActorSystem@127.0.0.1:8888/user/masterActor")

    //向master发送注册信息
    master ! "register"

  }

  override def receive: Receive = {
    case "start" => {
      println("a client connected")
    }
    //worker接收master注册成功的信息
    case "success" =>{
      println("register success")
    }
  }

}

object Worker{

  def main(args: Array[String]): Unit = {

    //定义worker的ip地址和端口 参数:127.0.0.1 6666
    val host = args(0)
    val port = args(1)

    val configStr: String =
      s"""
         |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
         |akka.remote.netty.tcp.hostname = "$host"
         |akka.remote.netty.tcp.port = "$port"
      """.stripMargin

    val config = ConfigFactory.parseString(configStr)

    //1.创建ActorSystem
    val workerActorSystem : ActorSystem = ActorSystem("workerActorSystem",config)

    //2.创建worker actor
    val workerActor: ActorRef = workerActorSystem.actorOf(Props(new Worker),"workerActor")

    //3.测试
    workerActor ! "start"

  }
}

先启动master,再启动worker,运行结果如下

master输出:

[INFO] [09/03/2019 09:06:59.805] [main] [Remoting] Starting remoting
[INFO] [09/03/2019 09:07:00.857] [main] [Remoting] Remoting started; listening on addresses :[akka.tcp://masterActorSystem@127.0.0.1:8888]
[INFO] [09/03/2019 09:07:00.859] [main] [Remoting] Remoting now listens on addresses: [akka.tcp://masterActorSystem@127.0.0.1:8888]
Master constructor invoked
preStart method invoked
a client connected
a client register

worker输出:
[INFO] [09/03/2019 09:08:55.068] [main] [Remoting] Starting remoting
[INFO] [09/03/2019 09:08:56.044] [main] [Remoting] Remoting started; listening on addresses :[akka.tcp://workerActorSystem@127.0.0.1:6666]
[INFO] [09/03/2019 09:08:56.045] [main] [Remoting] Remoting now listens on addresses: [akka.tcp://workerActorSystem@127.0.0.1:6666]
Worker constructor invoked
preStart method invoked
a client connected
register success

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值