scala基础之三 scala并发入门(akka之actor)

16 篇文章 0 订阅
5 篇文章 0 订阅

标签(空格分隔): hadoop scala


前言

前两节我们学习了scala的基础语法,包括基本类型,流程控制,模式匹配,和对应的类,对象,特征的定义,那么在java中我们知道,为了提高效率不可避免的会用到异步,线程提高我们的处理效率。今天我们来学习下scala的并发编程,闲话少说我们下面进入正题。

Actor

Actor基础类库使用简介

2.10之前是使用Actor作为并发编程模型,2.10以后采用Akka作为并发编程, 老版本的Actor已然废弃,但我们今天需要先学习下老版本的Actor学习一下编程模型和机制。
image_1dhnf14s01nenqpc162uif0a1b9.png-68.7kB
上图就是一个完美诠释Actor的多线程机制。
通过消息传递,类似投递箱 异步获取信息处理。所以人家与java的多线程机制有点不大一样,人家设计的这种就是通过尽可能避免锁争用和共享状态。让我们使用的时候更容易设计出线程安全的并发程序(但是如果涉及到actor内部操作外部的状态是可能存在线程安全问题的)。
actor中通常使用receive和react来完成获取消息处理流程。消息传递的方式有多种

符号描述
异步发送没有返回值
!!异步发送返回future
!?同步并等待消息返回

通常actor的设计尽量避免共享变量,比如我们通过actor完成消息处理后的汇总,我们可以使用ConcurrentHashMap来完成汇总,但在scala中你可以使用这个actor持有另外一个汇总acotr完成消息异步发送。
以下我们将进行actor的demo使用。

actor的demo

  package com.lcy.scalabasic.actors

/**
  * Created by luo on 2019/8/11.
  */
class ActorDemo extends actors.Actor{
  override def act(): Unit = {
    //循环获取消息,如果没有消息会Block
    while(true){
      receive {
        case "hello" => println("hello")
      }
    }
  }
}

class ActorDemo2 extends actors.Actor{
  //如果需要返回值可以使用这个方法,然后让消息方发送的消息使用!? 同步获取 但强烈不建议这样使用
  override def act(): Unit = {
      receive{
        case "hello" => sender ! "give you world"
      }
  }
}

class ActorDemo3 extends actors.Actor{
  override def act(): Unit = {
    //这回我们还是使用重复接受消息的形式,让actor可以一直获取消息
    while(true){
      receive{
        case "hello" => sender ! "i give you word"
      }
    }
  }
}

object ActorDemo{
  def main(args: Array[String]): Unit = {
    val ac = new ActorDemo
    ac.start()
    ac ! "hello"
    val ac2 = new ActorDemo2
    ac2.start()
    val result = ac2 !? "hello"
    println(s"syc result $result")
    val ac3 = new ActorDemo3
    ac3.start()
    val future = ac3 !! "hello"
    //FutureActor
    println(future.isSet)
    val c = future.apply()
    println(future.isSet)
    println(c)
  }
}

这里说明一下 receive之内其实是一个偏函数,当然您也不适用receive而直接起一个线程使用处理程序。

receive和react的区别

reactor会复用线程,避免频繁的创建和销毁线程
当使用receive时,程序为每个actor都单独创建一个线程,如没有接收到消息,该线程也会一直保持等待,不可以其他任务复用。
当使用react时,actor不会单独占用线程,只有当接收到消息程序才会为该actor分配线程,非常节省资源。(类似懒加载)

package com.lcy.scalabasic.actors

/**
  * Created by luo on 2019/8/11.
  */
class ActorReceive extends actors.Actor{
  override def act(): Unit = {
    while(true){
      receive{
        case "hello" => println("i am actorreceive thread of " + Thread.currentThread())
      }
    }
  }
}

class ActorReact extends actors.Actor{
  override def act(): Unit = {
    loop{//必须用loop快学scala中有解释 react处理完之后就退出所以没法返回到while循环中
      react{
        case "hello" => println("i am actorReact thread of " + Thread.currentThread())
      }
    }
  }
}

object ActorReceive{

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

    for(i <- 1 to 10){
      new ActorReceive().start() ! "hello"
    }
    for(i <- 1 to 10){
     new ActorReact().start ! "hello"
    }
  }
}

立个flag

在后续等有时间回过头来,写下针对Actor的相关其他概念,比如消息传递的种类,还有管道的使用等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值