用scala的actor并发编程写一个单机版的WorldCount
前言:最近一段时间比较忙,也是比较懒了吧,好长时间没写博客了,新的一年到来,给自己一个小目标,博客坚持写下去,分享一下这历程!废话不多说,开始正题咯(希望大家喜欢!)
首先这算是一个scala程序的入门程序,但是并不是针对零基础的,需要了解一定的scala基础,如果有Java基础的同学看起来估计会好一点。如果有必要的话,后面补一篇比较 详细的适合新手的零基础scala“教程”吧!
首先说明一下,Scala Actor是scala 2.10.x版本及以前版本的Actor。Scala在2.11.x版本中将Akka加入其中,作为其默认的Actor,老版本的Actor已经废弃,虽然已经废弃了,但是还是可以作为扩展去了解一下的。
这里普及一下java并发编程与Scala Actor编程的区别:

对于Java,我们都知道它的多线程实现需要对共享资源(变量、对象等)使用synchronized 关键字进行代码块同步、对象锁互斥等等。而且,常常一大块的try…catch语句块中加上wait方法、notify方法、notifyAll方法是让人很头疼的。原因就在于Java中多数使用的是可变状态的对象资源,对这些资源进行共享来实现多线程编程的话,控制好资源竞争与防止对象状态被意外修改是非常重要的,而对象状态的不变性也是较难以保证的。
与Java的基于共享数据和锁的线程模型不同,scala的actor包则提供了另外一种不共享任何数据、依赖消息传递的模型,从而进行并发编程。
Actor的执行顺序
1、首先调用start()方法启动Actor
2、调用start()方法后其act()方法会被执行
3、向Actor发送消息
4、act方法执行完成之后,程序会调用exit方法
发送消息的方式
|
! |
发送异步消息,没有返回值。 |
|
!? |
发送同步消息,等待返回值。 |
|
!! |
发送异步消息,返回值是 Future[Any]。 |
注意:Future 表示一个异步操作的结果状态,可能还没有实际完成的异步任务的结果
Any 是所有类的超类,Future[Any]的泛型是异步操作结果的类型。
正式进入正题,对!前面还是做了一些基本的介绍,方便大家的回忆!
我们的目标:用actor并发编程写一个单机版的WorldCount,将多个文件作为输入,计算完成后将多个任务汇总,得到最终的结果
大致思想步骤:
1、通过loop +react 方式去不断的接受消息(注意这里的消息就是我们当前的文件名称)
2、利用case class样例类去匹配对应的操作
3、其中scala中提供了文件读取的接口Source,通过 调用其fromFile方法去获取文件内容
4、将每个文件的单词数量进行局部汇总,存放在一个ListBuffer中
5、最后将ListBuffer中的结果进行全局汇总。
准备工作:在E盘放入三个文件,aa.txt、bb.txt、cc.txt随便写一些单词进去。




接下来就是写一个我们的WordCountScala.scala类了:
package com.yida.scala
import scala.actors.{Actor, Future}
import scala.collection.mutable
import scala.collection.mutable.ListBuffer
import scala.io.Source
//todo:利用scala中的并发编程,多个文件作为输入,首先进行局部汇总,最终再进行全部汇总
//todo:定义样例类
case class SubmitTask(fileName:String)//提交任务的样例类
case class ResultTask(result:Map[String,Int])//todo:封装每个单词出现的次数
class WordCountScala extends Actor{
override def act(): Unit = {
loop{
react{
case SubmitTask(fileName) => {
//todo:2、读取文件数据,利用scala中的scala.io.Source的fromFile方法读取数据
val lines: String = Source.fromFile(fileName).mkString
//todo:3、按照换行符进行读取,window下的换行符是 \r\n Linux是 \n
val linesArray: Array[String] = lines.split("\r\n")
println(linesArray.toBuffer)
//todo:4、按照空格进行切分并且压平
val words: Array[String] = linesArray.flatMap(_.split(" "))
println(words.toBuffer)
//todo:5、每个单词记为1
//words.map((_,1))
val wordAndOne: Array[(String, Int)] = words.map(x=>(x,))
println(wordAndOne.toBuffer)
//todo:6、按照单词进行分组
val wordGroup: Map[String, Array[(String, Int)]] = wordAndOne.groupBy(_._1)
println(wordGroup.toBuffer)
//todo:7、通过mapValues方法拿到map所有key对应的value
val result: Map[String, Int] = wordGroup.mapValues(_.length)
println(result.toBuffer)
//todo:8、把结果返回给发送方
sender ! ResultTask(result)
}
}
}
}
}
object WordCountScala{
def main(args: Array[String]): Unit = {
//todo:定义一个set集合 ,用于存放每次异步的结果
val hashSet = new mutable.HashSet[Future[Any]]()
//todo:定义一个list集合,用于存放真正的结果数据
val taskList = new ListBuffer[ResultTask]
/*
val task = new WordCountScala
task.start()
task !! SubmitTask("E:\\aa.txt")*/
//todo:1、准备数据文件
val files = Array("E:\\aa.txt","E:\\bb.txt","E:\\cc.txt")
//todo:2、遍历数据文件,发送消息
for(fileName <- files){
//todo:3、针对每一个文件,创建一个actor实例
val task = new WordCountScala
task.start()
//向actor提交任务
val result: Future[Any] = task !! SubmitTask(fileName)
//todo:4、存放异步返回结果到set集合中
hashSet += result
}
//todo:5、处理hashSet中的数据
while(hashSet.size>){
//todo:6、判断对应真正完成任务的结果
val completedTask: mutable.HashSet[Future[Any]] = hashSet.filter(_.isSet)
for(c <- completedTask){
//todo:7、获取future中的数据
val data: Any = c.apply()
val task: ResultTask = data.asInstanceOf[ResultTask]
//todo:8、将真正的结果保存到list集合中
taskList += task
//todo:9、将处理完成的数据删除
hashSet -= c
}
}
//todo:10、对taskList结果进行操作
println(taskList.map(_.result).flatten.groupBy(_._1).mapValues(x=>x.foldLeft()(_+_._2)))
}
}
欣赏一下跑完后的结果:代码 注释还有 不懂的地方 欢迎提出来,我看到了会解答的哈!

用scala的actor并发编程写一个单机版的WorldCount的更多相关文章
- 【Scala】Actor并发编程实现单机版wordCount
文章目录 对单个文本文件进行单词计数 对多个文本文件进行单词计数 对单个文本文件进行单词计数 import scala.actors.Actor import scala.io.Source //读取 ...
- scala当中的Actor并发编程
注:Scala Actor是scala 2.10.x版本及以前版本的Actor. Scala在2.11.x版本中将Akka加入其中,作为其默认的Actor,老版本的Actor已经废弃. 1.什么是Sc ...
- 【并发编程】一个最简单的Java程序有多少线程?
一个最简单的Java程序有多少线程? 通过下面程序可以计算出当前程序的线程总数. import java.lang.management.ManagementFactory; import java. ...
- Scala 并行和并发编程-Futures 和 Promises【翻译】
官网地址 本文内容 简介 Futures 阻塞 异常 Promises 工具 最近看了<七周七语言:理解多种编程泛型>,介绍了七种语言(四种编程范型)的主要特性:基本语法,集合,并行/并发 ...
- scala中java并发编程
Runnable/Callable 线程(Thread) Executors/ExecutorService Future 线程安全问题 示例:搜索引擎 解决方案 Runnable/Callable ...
- 编程写一个方法时,注意方法中传参数的数量最好不要超过5个,超过5个怎么办?可以用struct或class,或一个字典类
图 1 一.从图1发现了什么问题呢? 答案:1.参数传的的太多了:2.另外注释也没写好. 说明:一个方法中,传参数的数量最好不要超过5个. 应该采用:struct或class,或一个字典类都行.其中 ...
- Python并发编程-线程-一个简单的例子
from threading import Thread import time def func(n): #子线程完成的 time.sleep(1) print(n) #多线程示例 for i in ...
- Scala学习之路 (十)Scala的Actor
一.Scala中的并发编程 1.Java中的并发编程 ①Java中的并发编程基本上满足了事件之间相互独立,但是事件能够同时发生的场景的需要. ②Java中的并发编程是基于共享数据和加锁的一种机制,即会 ...
- java并发编程 --并发问题的根源及主要解决方法
目录 并发问题的根源在哪 缓存导致的可见性 线程切换带来的原子性 编译器优化带来的有序性 主要解决办法 避免共享 Immutability(不变性) 管程及其他工具 并发问题的根源在哪 首先,我们要知 ...
随机推荐
- 牛客网Java刷题知识点之基本数据类型参数传递和引用数据类型参数传递图解
不多说,直接上干货! //基本数据类型参数传递 class Demo { public static void main(String[] args) { ; show(x); System.out. ...
- 用boost模块加速你的drupal站
boost模块可以对 html, xml, ajax, css, javascript进行缓存,极大提升游客访问的速度,几乎可以和静态页面媲美.下载boost http://drupal.org/p ...
- 深入V8引擎-Time核心方法之win篇(2)
这一篇讲windows系统下TimeTicks的实现. 对于tick,V8写了相当长的一段discussion来讨论windows系统上计数的三种实现方法以及各自的优劣,注释在time.cc的572行 ...
- The program 'unzip' is currently not installed. You can install it by typing:
linux解压遇到下面问题: The program 'unzip' is currently not installed. You can install it by typing: sudo ap ...
- window mysql5.7 zip 安装
第一步 ? 1 2 3 4 5 6 7 8 9 10 11 12 my-default.ini 添加配置: #绑定IPv4和3306端 bind-address = 127.0.0.1 port = ...
- 【经验总结】datagrid锁定列后重新加载时出现错位问题的解决
[问题描述]:有时候datagrid设置了锁定列后,在重新加载datagrid数据时,出现锁定列与非锁定列数据错位的问题,如图: [问题分析]:查看css样式我们发现,锁定的列和非锁定的列属于两个不同 ...
- web开发模式小结:页面乱码和跳转
本文由付老师总结书写 java开发模式: (1)第一种开始模式:javaBean+jsp : 优点:可以为web程序在jsp中减少java代码量 适用于该开发模式的jsp的动作元素:<jsp:u ...
- <Android 基础(一)> Service
介绍 Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件.其他应用组件能够启动Service,并且当用户切换到另外的应用场景,Service将持续在后台运行.另外,一个组件能够 ...
- Apache Spark 2.2.0 中文文档 - GraphX Programming Guide | ApacheCN
GraphX Programming Guide 概述 入门 属性 Graph 示例属性 Graph Graph 运算符 运算符的汇总表 Property 运算符 Structural 运算符 Joi ...
- co-dialog弹出框组件-版本v2.0.1
具体案例查看co-dialog:https://koringz.github.io/co-dialog/index.html 2.0.1版本优化项,代码压缩,修复PC和移动端自适应,修复显示弹出框浏览 ...