使用scala的Actor模拟计算多文件WordCount

scala的Actor是基于事件模型的,具体的模型可以自己查询资料,这里根据别人的demo代码自己也写了一个基于Actor的事件模型的多文件计算WordCount,代码中我写了详细的注释,仅供参考

首先在D盘下面创建三个文件,里面写一些单词用空格分开:

这里写图片描述

具体代码如下:

package com.lijie.actor

import scala.actors._
import scala.collection.mutable
import scala.collection.mutable.ListBuffer
import scala.io.Source

/**
  * Created by Lijie on 2017/3/22.
  */
class MyActor extends Actor {

  //重写Actor中的act()方法,和java中的run()一样
  override def act(): Unit = {

    //相当于while(true)  这里用react可以复用线程池
    loop {

      //这是个偏函数,定义两个模式匹配
      react {
        case MapCalculation(fileName) => {

          //计算文件中的word的数量,并用sender把消息发送回去
          sender ! MapResult(Source.fromFile(fileName).getLines().flatMap(_.split(" ")).map((_, 1)).toList.groupBy(_._1).mapValues(_.size))
        }
      }
    }
  }
}

//定义一个case class 用来模拟map的word统计
case class MapCalculation(fileName: String)

//定义一个case class 用来模拟map的word统计的返回结果封装
case class MapResult(mapResult: Map[String, Int])

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

    //用来存储异步返回的future
    val futures = new mutable.HashSet[Future[Any]]()

    //用来存储map返回的值
    val listRes = new ListBuffer[Map[String, Int]]()

    //定义文件的位置,类似于mapreduce的FileInputFormat.addInputPath
    val files = Array("D:\\lijietest01.txt", "D:\\lijietest02.log", "D:\\lijietest03.txt")

    //循环向MyActor发送消息
    for (fileName <- files) {

      //创建消息对象 并启动  且发送异步消息
      //每启动一个发送一个异步消息并返回一个Future,这里同java中的Callable
      val actor = new MyActor

      //发送异步消息并返回Future(!   !?    !!)
      val future = actor.start() !! MapCalculation(fileName)

      //扔到hashSet中
      futures += future
    }

    //模拟reduce
    while (futures.size > 0) {

      //这里取出已经计算完成的异步返回 isSet类似于Callable的isDone返回boolean,将计算完的结果放到res
      val res = futures.filter(_.isSet)

      for (r <- res) {

        //这里的apply()相当于Callable的get(),强转成MapResult(上面那个case class),取出里面的map并且放入到一个list中
        listRes += r.apply().asInstanceOf[MapResult].mapResult

        //移除futures已经处理的对象,直到移除完 这个while循环就终止
        futures -= r

        //如果文件很大,最后设定睡眠时间,不然cpu会空跑
        Thread.sleep(100)
      }
    }

    //对上面处理完成的map结果进行reduce
    //其中这个listRes打印出来如下:(因为我这里三个文件内容一样,所以每个map里面的数据一样)
    // ListBuffer(
    // Map(world -> 1, soga -> 1, scala -> 2, lijie -> 4, abcd -> 1, hello -> 3, nihao -> 1),
    // Map(world -> 1, soga -> 1, scala -> 2, lijie -> 4, abcd -> 1, hello -> 3, nihao -> 1),
    // Map(world -> 1, soga -> 1, scala -> 2, lijie -> 4, abcd -> 1, hello -> 3, nihao -> 1)
    // )
    val wordCount = listRes.flatten.groupBy(_._1).mapValues(_.foldLeft(0)(_ + _._2))

    //测试打印结果
    //Map(world -> 3, soga -> 3, scala -> 6, lijie -> 12, abcd -> 3, hello -> 9, nihao -> 3)
    println(wordCount)
  }
}

运行结果如下:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值