Scala-Actor简介并实现WordCount实例

                       Scala-Actor简介并实现WordCount实例

一、为什么学习actor

scala actor 是scala 2.10.x 版本及以前版本的 Actor。

scala 在2.11.x 版本中将Akka加入。作为默认的Actor。老版本的Actor已经废弃。

学习actor为了学习AKKa做铺垫。

二、什么是Actor

Actor是消息并发模型。

scala中的Actor能够实现并行编程的强大功能。它是基于事件模型的并发机制。

scala是运用消息(message)的发送、接收来实现多线程的。

使用scala能够更容易的实现多线程应用开发。

三、Java并发编程与Scala Actor 并发编程的区别。

3.1 scala的Actor类似于Java中的多线程编程。但是不同的是,scala的Actor提供的模型与多线程有所不同。

3.2 scala的Actor尽可能的避免锁和共享状态。从而实现多线程并发时,资源征用的情况,进而提升多线程编程的性能。

3.3 sacal的模型还可以避免死锁等一系列传统多线程编程的问题。Java中多数使用的是可变状态的使用对象资源。对这些资源共享来实现多线程编程的话,控制好资源竞争与防止对象状态被意外修改是非常重要的。而对象状态不变形也是较难保证的。而在scala中我们可以通过复制不可变状态资源(即对象、scala中一切都是对象,方法、函数也是对象)的一个副本,再基于actor消息发送、接收机制进行并发编程。

四、Actor方法执行顺序

4.1 调用start()方法启动Actor

4.2 执行act()方法

4.3 向Actor发送消息

五、发送消息的方式

  --> 发送异步消息,没有返回值

!?  -->发送同步消息,等待返回值。

!!  -->发送异步消息,返回值是 Future[Any] 
 

六、Actor简单举例功能实现

任务实现:
*     1,创建一个Actor
*     2,Actor的消息接收和发送。
*     3,用Actor并发编程实现WordCount

详细编程如下:

package day04

import scala.actors.Actor

/**
  * 任务实现:
  *    
  *               1,创建一个Actor
  */
class ActorDemo {

}

object ActorDemo01 extends Actor{
  override def act(): Unit = {
    for (i <- 1 to 10){
      println("Actor01..."+i)
//      Thread.sleep(1000)

    }
  }
}

object ActorDemo02 extends Actor{
  override def act(): Unit = {
    for (i <- 1 to 10){
      println("Actor02..."+i)
//      Thread.sleep(1000)

    }
  }
}

object ActorDemo{
  def main(args: Array[String]): Unit = {
    ActorDemo01.start()
    ActorDemo02.start()

  }
}
package day04

import scala.actors.Actor


/**
  *
  * 2,Actor的消息接收和发送。
  */
class ActorDemo001 extends Actor {
  override def act(): Unit = {

    while (true) {

      //偏函数
      receive {
        case "start" => println("starting......")
        case AsynMes(id, msg) => {
          println(s"case id: $id,AsynMes: $msg")
          Thread.sleep(2000)
          sender ! ReplyMsg(5, "异步接收到了~~")
        }
        case SyncMsg(id, msg) => {
          println(s"case id: $id,SyncMsg: $msg")
          Thread.sleep(2000)
          sender ! ReplyMsg(5, "同步接收到了~~")
        }
      }
    }

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

     /*
      * 流程过程。
      * 1,新建一个ActorDemo01并且进行启动。
      * 2,给ActorDemo01发送一个没有返回值的异步消息。
      *
      */
    val actorDemo0 = new ActorDemo001
    actorDemo0.start()
    actorDemo0 ! AsynMes(12,"小伙子,我给你了异步")
    println("AsynMes 异步消息没有返回值发送完成")

    val resultSyncMsg:Any = actorDemo0 !? SyncMsg(13,"小伙子,我要给你有返回值的同步消息")
    println("SyncMsg 同步消息有返回值发送完成")
    println("resultSyncMsg 上面返回:   "+ resultSyncMsg)

    val resultAsynMes = actorDemo0 !! AsynMes(888, "小伙子,我给你发了异步,需要你的返回")
    println("AsynMes 异步消息有返回值发送完成")
    Thread.sleep(10000)
    if(resultAsynMes.isSet){  //判断是否有值。若有值---
      println("异步返回值: "+resultAsynMes.apply())   //resultAsynMes.apply() 取里面的值。
    }else{
      println("none")
    }
    //发送消息,没有返回值

  }
}

case class AsynMes(id: Int, msg: String) //异步消息

case class SyncMsg(id: Int, msg: String) //同步消息
case class ReplyMsg(id: Int, msg: String)
package day04

import scala.actors.{Actor, Future}
import scala.collection.mutable.ListBuffer
import scala.io.Source

/**
  * 3,用Actor并发编程实现WordCount
  */
class ActorWordCount {


}

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

    val replies: ListBuffer[Future[Any]] = new ListBuffer[Future[Any]]

    //存放有值的Future 里的数据
    val res: ListBuffer[Map[String, Int]] = new ListBuffer[Map[String,Int]]
    //读取文件内容
    val files: Array[String] = Array("C:\\Users\\Administrator\\Desktop\\Actor\\a.txt", "C:\\Users\\Administrator\\Desktop\\Actor\\a.txt", "C:\\Users\\Administrator\\Desktop\\Actor\\a.txt")
    for (file <- files) {

      /*
      //同步操作。

      val lines = Source.fromFile(file).getLines().toList

      val wordsList:List[String] = lines.flatMap(_.split(" "))

      val wordCount: Map[String, Int] = wordsList.map((_, 1)).groupBy(_._1).mapValues(_.size)

       */
      //开启Actor后,接收file的数据
      val actorFile = new ActorFile
      actorFile.start()
      val wordCount: Future[Any] = actorFile !! smTask(file)
      //用ListBuffer集合进行接收数据
      replies += wordCount

    }

    /*
    验证数据集 replies 是否为空,并接收里面的数据
     */
    while (replies.size > 0){
      //获取不为空的listBuffer
      val repliesRealy: ListBuffer[Future[Any]] = replies.filter(_.isSet)

      for(repliesRealyOne <- repliesRealy){
        res += repliesRealyOne.apply().asInstanceOf[Map[String,Int]]
        replies -= repliesRealyOne

      }

    }
    val wordCountResult: Map[String, Int] = res.flatten.groupBy(_._1).mapValues(_.foldLeft(0)(_+_._2))
    println(wordCountResult)

  }
}

class ActorFile extends Actor {
  override def act(): Unit = {
    while (true) {
      receive({
        case smTask(file) => {
          val lines = Source.fromFile(file).getLines().toList

          val wordsList: List[String] = lines.flatMap(_.split(" "))

          val wordCount: Map[String, Int] = wordsList.map((_, 1)).groupBy(_._1).mapValues(_.size)

          //异步发送数据,不要求有返回值
          sender ! wordCount

        }

      })
    }

  }

}
case class smTask(file: String)

欢迎订阅关注公众号(JAVA和人工智能)

                                                           获取更多免费书籍、资源、视频资料                                                     

文章超级链接:

 1,分布式系统详解--基础知识(概论)

 2,分布式系统详解--基础知识(线程)

 3,IDEA和Eclipse的比较

 4,IntelliJ IDEA(最新)安装-破解详解--亲测可用

 5,scala-构造器-辅助构造器-伴生对象-单例对象

 6,【由浅入深】爬虫技术,值得收藏,来了解一下~

你可能感兴趣的:(Scala)