Scala Actor编程之WordCount

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值