[Scala] Actor 相关

概念

学习路线
Actor --> Akka --> Spark

Actor:是消息并发模型

scala中的Actor能够实现并行编程的强大功能,它是基于事件模型的并发机制。scala是运用消息(message)的发送、接收来实现多线程的。

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

Java并发编程与scala Actor编程的区别

Scala的actor类似于Java中的多线程编程。但是不同的是,scala的Actor提供的模型与多线程有所不同,scala的Actor尽可能地避免锁和共享状态,从而避免多线程并发时出现资源争用的情况,进而提升多线程编程的性能。此外,scala actor的这种模型还可以避免死锁等一系列传统多线程编程的问题。原因就在于Java中多数使用的是可变状态的对象资源,对这些资源进行共享来实现多线程编程的话,控制好资源竞争与防止对象状态被意外修改是非常重要的,而对象状态的不变性也是较难以保证的。而在scala中,我们可以通过复制不可变状态的资源〈即对象,scala中一切都是对象,连函数、方法也是〉的一个副本,再基于Actor的消息发送、接收机制进行并行编程。

Actor 方法执行顺序

  1. 调用start()方法启动Actor
  2. 执行act()方法
  3. 向Actor发送消息

发送消息的方式
4. ! -->发送异步消息,没有返回值
5. !? -->发送同步消息,等待返回值
6. !! -->发送异步消息,返回值是Future[Any]

简单练习

package day05

import scala.actors.Actor

class ActorDemo1 {

}

// 重写act方法
object ActorDemo1 extends Actor{
  override def act(): Unit = {
    for (i<-1 to 20){
      println("actor1:"+i)
      Thread.sleep(1000)
    }
  }
}

object ActorDemo2 extends Actor{
  override def act(): Unit = {
    for (i<-1 to 20){
      println("actor2:"+i)
      Thread.sleep(1000)
    }
  }
}

object ActorTest{
  def main(args: Array[String]): Unit = {
    // 启动Actor
    ActorDemo1.start()
    ActorDemo2.start()
  }
}

三种消息发送方式的练习

package day05

import scala.actors.{Actor, Future}

/**
 * 用Actor实现同步和异步的消息的发送和消息的接收
 */

class ActorDemo3 extends Actor {
  override def act(): Unit = {
    while (true) {
      // 偏函数
      receive {
        case "start" => println("starting...")
        case AsyncMsg(id, msg) => {
          println(s"id:$id,AsyncMsg:$msg")
          Thread.sleep(2000)
          sender ! ReplyMsg(5, "success")
        }
        case SyncMsg(id, msg) => {
          println(s"id:$id,SyncMsg:$msg")
          Thread.sleep(2000)
          sender ! ReplyMsg(5, "success")
        }
      }
    }
  }
}

case class AsyncMsg(id: Int, msg: String)

case class SyncMsg(id: Int, msg: String)

case class ReplyMsg(id: Int, msg: String)

object ActorDemo3 {
  def main(args: Array[String]): Unit = {
    val actorDemo3: ActorDemo3 = new ActorDemo3
    actorDemo3.start()

//    // 异步发送消息,没有返回值
//    actorDemo3 ! AsyncMsg(1, "Hi~ ,Li")
//    println("没有返回值的异步消息发送完成")
//
//    // 同步发送消息,线程等待返回值
//    val content: Any = actorDemo3 !? SyncMsg(2, "Hi~ ,Wang")
//    println("有返回值的同步消息发送完成")
//    println(content)

    // 异步发送消息,有返回值,返回类型是Future[Any]
    val reply: Future[Any] = actorDemo3 !! AsyncMsg(3, "Hi~ ,Zhao")
//    Thread.sleep(5)
    Thread.sleep(3000)
    if (reply.isSet){
      val value=reply.apply()
      println(value)
    }else{
      println("None")
    }
  }
}

实现wordcount

package day05

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

/**
 * 用Actor并发编程实现WordCount
 */


class ActorWordCount {

}

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

    // 存放接收到的每个文件的结果数据
    val replys: ListBuffer[Future[Any]] = new ListBuffer[Future[Any]]

    // 存放有值的Future里的数据
    val res: ListBuffer[Map[String, Int]] = new ListBuffer[Map[String, Int]]

    val files: Array[String]
    = Array(
      "E:\\test\\a.txt",
      "E:\\test\\b.txt",
      "E:\\test\\c.txt"
    )

    for (file <- files) {
      //      val lines: List[String] = Source.fromFile(file).getLines().toList
      //      val words: List[String] = lines.flatMap(_.split(" "))
      //      val res: Map[String, Int] = words.map((_, 1)).groupBy(_._1).mapValues(_.size)
      val task = new Task
      task.start()

      // 接收结果数据,异步发送消息,有返回值
      val reply: Future[Any] = task !! SmTask(file)

      replys += reply
    }
    while (replys.size > 0) {

      // 过滤每个Future对象,如果None类型的,就过滤掉
      val dones: ListBuffer[Future[Any]] = replys.filter(_.isSet)

      for (done <- dones) {
        res += done.apply().asInstanceOf[Map[String, Int]]

        replys -= done
      }
    }
    // flatten 压平,根据key进行分组,对值进行求和
    val map = res.flatten.groupBy(_._1).mapValues(_.foldLeft(0)(_ + _._2))
    println(map)
  }
}


class Task extends Actor {
  override def act(): Unit = {
    while (true) {
      receive({
        case SmTask(file) => {
          val lines: List[String] = Source.fromFile(file).getLines().toList
          val words: List[String] = lines.flatMap(_.split(" "))
          val res: Map[String, Int] = words.map((_, 1)).groupBy(_._1).mapValues(_.size)

          // 异步发送结果数据,没有返回值
          sender ! res
        }
      })
    }
  }
}

// 整理成偏函数,然后调用,后期方便修改
case class SmTask(file: String)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值