Scala中的Actor能够实现并行编程的强大功能,它是基于时间模型的并发机制,Scala是运用消息(message)的发送、接收来实现多线程的.使用Scala能够更容易的实现多线程应用的开发.
1.Actor方法执行顺序
1)首先调用start()方法启动Actor
2)调用start()方法后act()方法将执行
3)向Actor发送消息
2.发送消息的方式
1)! 发送异步消息,没有返回值
2)!? 发送同步消息,等待返回值
3)!! 发送异步消息,返回值是Future[Any]
两个Actor并行执行,调用start()方法后,act()方法执行
package com.scala.actor
import scala.actors.Actor
object ActorDemo extends Actor{
// 重写act方法
override def act(): Unit = {
for (i <- 1 to 10){
println("actor1:"+i)
Thread.sleep(1000)
}
}
}
object ActorDemo2 extends Actor{
override def act(): Unit = {
for (i <- 1 to 10){
println("actor2:"+i)
Thread.sleep(1000)
}
}
}
object ActorTest extends App{
// 启动
ActorDemo.start()
ActorDemo2.start()
}
不断接收消息(发送消息是异步的,但是Actor接收到消息执行的过程是同步的按顺序执行),通过while(true)的方式
package com.scala.actor
import scala.actors.Actor
class ScalaActor extends Actor{
override def act(): Unit = {
while(true){
receive{
case "start" => {
println("starting...")
Thread.sleep(2000)
println("started")
}
case "stop" => {
println("stopping...")
Thread.sleep(2000)
println("stopped")
}
}
}
}
}
object ScalaActor{
def main(args: Array[String]){
val actor = new ScalaActor
actor.start()
actor ! "start"
actor ! "stop"
println("消息发送完成")
}
}
不断接收消息(react方式会复用线程,比receive更高效)react外层要用loop
package com.scala.actor
import scala.actors.Actor
class ScalaActor extends Actor{
override def act(): Unit = {
loop{
react{
case "start" => {
println("starting...")
Thread.sleep(2000)
println("started")
}
case "stop" => {
println("stopping...")
Thread.sleep(2000)
println("stopped")
}
}
}
}
}
object ScalaActor{
def main(args: Array[String]){
val actor = new ScalaActor
actor.start()
actor ! "start"
actor ! "stop"
println("消息发送完成")
}
}
结合case class发送消息
package com.scala.actor
import scala.actors.Actor
/**
* actor的三种发送消息模式 ! !? !!
*/
class CaseClassActor extends Actor{
override def act(): Unit = {
while(true){
receive{
case "start" => {print("start...")}
case AsyMSG(id,msg) => {
println(id+",Asy,"+msg)
}
case SynMSG(id,msg) => {
println(id+",Syn,"+msg)
sender !SynMSG(3,"finished")
}
}
}
}
}
case class AsyMSG(id:Int,msg:String)
case class SynMSG(id:Int,msg:String)
object CaseClassActor{
def main(args: Array[String]): Unit = {
val actor = new CaseClassActor
actor.start()
/* actor !AsyMSG(1,"I am Asy")
println("异步消息发送成功")*/
val returnval = actor !?(1000,SynMSG(2,"I am Syn"))
println(returnval)
println("同步消息返回值获取成功")
val Futurevalue = actor !!SynMSG(4,"I am Syn and have returnvalue")
println(Futurevalue.isSet)
val c = Futurevalue.apply()
println(c)
println(Futurevalue.isSet)
}
}
Scala WordCount
package com.scala.actor
import scala.actors.{Actor, Future}
import scala.collection.mutable
import scala.collection.mutable.ListBuffer
import scala.io.Source
class ActorWordCount extends Actor{
override def act(): Unit = {
loop{
react{
case MapTask(filename) => {
// map的业务逻辑 1.读取文件 2.单词切割 3.(key,1) 4.combiner
// 局部汇总,结果是Map[String,Int]
val result = Source.fromFile(filename).getLines().flatMap(_.split(" ")).map((_,1)).toList.groupBy(_._1).mapValues(_.size)
// 将Map结果发送给reduce
sender !ReduceTask(result)
}
case ExistTask => {
exit()
}
}
}
}
}
object ActorWordCount{
def main(args: Array[String]): Unit = {
val resSet = new mutable.HashSet[Future[Any]]()
val resultList = new ListBuffer[ReduceTask]
val files = Array[String]("d://words.txt","d://MR.txt")
for(filename <- files){
val actor = new ActorWordCount
//启动actor并向MapTask发送消息,返回值是一个Future
val res = actor.start() !! MapTask(filename)
// 把这些Future(res)放到集合中
resSet += res
}
while(resSet.size > 0){
// 取出有效的结果集,待处理的数据
val toHandle = resSet.filter(_.isSet)
for(f <- toHandle){
val result = f.apply()
// 获取ReduceTask一个实例
val result1 = result.asInstanceOf[ReduceTask]
// 将有效的数据放到另一个容器中
resultList += result1
// 从future的集合中删除用过的元素,防止死循环
resSet -= f
}
}
// resultList:((hello,3),(hello,2),(tom,1)...)此时是一个wordcount
val rd = resultList.flatMap(_.result).groupBy(_._1).mapValues(_.foldLeft(0)(_+_._2))
print(rd.toBuffer)
}
}
case class MapTask(filename:String)
case class ReduceTask(result:Map[String,Int])
case object ExistTask