Scala系列:Actor创建,Actor发送,接受消息等详解与案例演示

444 阅读3分钟

0.Actor介绍

scala的Actor并发编程模型可以用来开发比Java线程效率更高的并发程序。我们学习scala Actor的目的主要是为后续学习Akka做准备。

0.1 Java并发编程的问题

在Java并发编程中,每个对象都有一个逻辑监视器(monitor),可以用来控制对象的多线程访问。我们添加sychronized关键字来标记,需要进行同步加锁访问。这样,通过加锁的机制来确保同一时间只有一个线程访问共享数据。但这种方式存在资源争夺、以及死锁问题,程序越大问题越麻烦。

线程死锁

0.2 Actor并发编程模型

Actor并发编程模型,是scala提供给程序员的一种与Java并发编程完全不一样的并发编程模型,

  1. Actor是一种基于事件模型的并发机制。
  2. Actor并发编程模型是一种不共享数据,依赖消息传递的一种并发编程模式,有效避免资源争夺、死锁等情况。

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

1.Actor的使用|创建Actor

创建Actor的方式和Java中创建线程很类似,也是通过继承来创建。类似于Java线程,这里的每个Actor是并行执行的。

1.1Actor使用方式

  1. 定义class或object继承Actor特质,去别是前者可以new多个对象,后者只有一个。
  2. 重写act方法
  3. 调用Actor的start方法执行Actor

1.2示例说明

创建两个Actor,一个Actor打印1-10,另一个Actor打印11-20

  • 使用class继承Actor创建(如果需要在程序中创建多个相同的Actor)
  • 使用object继承Actor创建(如果在程序中只创建一个Actor)

参考代码

使用class继承Actor创建,三个Actor并行执行。

import scala.actors.Actor

object _08ObjectDemo {
  class Actor1 extends Actor {
    override def act(): Unit = (1 to 10).foreach(x=>print(" "+x))
  }
  class Actor2 extends Actor {
    override def act(): Unit = (11 to 20).foreach(x=>print(" "+x))
  }
  def main(args: Array[String]): Unit = {
    new Actor1().start()
    new Actor2().start()
    new Actor2().start() //定义的class的Actor可以new多个
  }
}/**
11 11 1 12 12 13 2 14 13 15 3 16 14 17 4 18 15 19 5 20 16 6 17 7 18 8 19 9 20 10
  */

使用object继承Actor创建,不能new多个。

package com.robot.scalademo
import scala.actors.Actor

object _08ObjectDemo {
  object Actor1 extends Actor {
    override def act(): Unit =
      for(i <- 1 to 10) {
        print(" "+i)
      }
  }

  object Actor2 extends Actor {
    override def act(): Unit =
      for(i <- 11 to 20) {
        print(" "+i)
      }
  }

  def main(args: Array[String]): Unit = {
    Actor1.start()
    Actor2.start()
  }
}/**
11 1 2 12 3 13 4 14 5 15 6 7 16 8 17 9 18 10 19 20
  */

尖叫提示:Actor的内部运行流程

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

2.Actor发送消息/接收消息

我们之前介绍Actor的时候,说过Actor是基于事件(消息)的并发编程模型,那么Actor是如何发送消息和接收消息的呢?

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

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

actor1 ! "你好!"

2.1 接收消息

  1. Actor中使用receive方法来接收消息,需要给receive方法传入一个偏函数
  2. receive方法只接收一次消息,接收完后继续执行act方法
{
    case 变量名1:消息类型1 => 业务处理1,
    case 变量名2:消息类型2 => 业务处理2,
    ...
}

示例说明

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

参考代码 

package com.robot.scalademo
import scala.actors.Actor
import scala.actors.threadpool.TimeUnit

object _08ObjectDemo {
  object ActorSender extends Actor {
    override def act(): Unit = {
      // 发送消息
      while(true) {
        ActorReceiver ! "hello!"  //注意这里的对象是ActorReceiver,不是ActorSender对象
        TimeUnit.SECONDS.sleep(3)
      }
    }
  }
  object ActorReceiver extends Actor {
    override def act(): Unit = {
      // 持续接收消息
      while(true) {
        receive {
          case msg:String => println("接收到消息:" + msg)
        }
      }
    }
  }
  def main(args: Array[String]): Unit = {
    ActorReceiver.start()
    ActorSender.start()
  }
}/**
接收到消息:hello!
接收到消息:hello!
接收到消息:hello!
接收到消息:hello!
接收到消息:hello!
  */