0.Actor介绍
scala的Actor并发编程模型可以用来开发比Java线程效率更高的并发程序。我们学习scala Actor的目的主要是为后续学习Akka做准备。
0.1 Java并发编程的问题
在Java并发编程中,每个对象都有一个逻辑监视器(monitor),可以用来控制对象的多线程访问。我们添加sychronized关键字来标记,需要进行同步加锁访问。这样,通过加锁的机制来确保同一时间只有一个线程访问共享数据。但这种方式存在资源争夺、以及死锁问题,程序越大问题越麻烦。
线程死锁
0.2 Actor并发编程模型
Actor并发编程模型,是scala提供给程序员的一种与Java并发编程完全不一样的并发编程模型,
- Actor是一种基于事件模型的并发机制。
- Actor并发编程模型是一种不共享数据,依赖消息传递的一种并发编程模式,有效避免资源争夺、死锁等情况。
0.3 Java并发编程对比Actor并发编程
1.Actor的使用|创建Actor
创建Actor的方式和Java中创建线程很类似,也是通过继承来创建。类似于Java线程,这里的每个Actor是并行执行的。
1.1Actor使用方式
- 定义class或object继承Actor特质,去别是前者可以new多个对象,后者只有一个。
- 重写act方法
- 调用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的内部运行流程
- 调用start()方法启动Actor
- 自动执行act()方法
- 向Actor发送消息
- act方法执行完成后,程序会调用exit()方法
2.Actor发送消息/接收消息
我们之前介绍Actor的时候,说过Actor是基于事件(消息)的并发编程模型,那么Actor是如何发送消息和接收消息的呢?
我们可以使用三种方式来发送消息:
要给actor1发送一个异步字符串消息,使用以下代码:
actor1 ! "你好!"
2.1 接收消息
- Actor中使用receive方法来接收消息,需要给receive方法传入一个偏函数
- 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!
*/