scala系列--并发01

2023-06-29 16:47:02 浏览数 (1)

  最近研究了一些scala并发的知识,总结一下。

一.简介

即时响应性是一项决定任何应用程序成败的关键因素。有两种方式来提高即时响应性:1.多线程,并行运行多个任务。2.有策略的计算,惰性运行任务。

二.惰性求值

1.短路控制,scala不会向前看,所以用到lazy。 注意:多个变量绑定,后续调用,顺序不可预知。

2.惰性集合,创建临时视图,调用的时候立即求值。

3.无限流转换有限流

有限序列

无限流-》Stream

三.并行集合

顺序集合

顺序集合上的方法行为:它们为它们的集合中的每个元素顺序地执行它们的操作。

并行集合

,Scala 都拥有其并行版本。例如,ParArray 是Array 对应的并行版本,同样的,ParHashMap、ParHashSet 和ParVector 分别对应于HashMap、HashSet 和Vector。我们可以使用par()和seq()方法来在顺序集合及其并行版本之间进行相互转换。

四.Actor

简介:

 Acotr模式是一种并发模型与另一种模型共享内存完全相反,Actor模型share nothing。  所有线程(或进程)通过消息传递方式进行合作,这些线程(或进程)称为Actor,共享内存更适合单机多核的并发编程。

特点:

  • 保证互斥访问的活动对象。
  • 一个Actor将只会处理一条消息。Actor模型具有与生俱来的线程安全性。
  • 多个Actor并发地运行,同时处理多条消息。
  • Actor是异步。
  • 不会阻塞调用者。
  • 不用显示创建一个线程池,显示调度任务。
  • 线程并不和Actor绑定--一个线程池服务于多个Actor。
  • java创建共享可变变量,并使用同步原语来提供线程安全性。使用JDK 库很难在短时间内做到正确的并发。

注意:

  • 更多依赖无状态Actor,少用有状态Actor。
  • 确保Actor之间传递消息是不可变对象(case,String,Int等)。保证我们不会无意间修改共享状态。
  • 尽量避免使用ask().双向通信不是一个好主意。“发送并忘记”(!)模型好得多。

示例:

统计字符串的次数。

代码语言:javascript复制
import akka.actor._
import scala.collection.mutable
/**
  * 接收消息
  */
class MessageActor extends Actor{
  val messagesCount: mutable.Map[String, Int] =mutable.Map()
  override def receive: Receive = {
    case Play(role) =>
      val currentCount = messagesCount.getOrElse(role, 0)
      messagesCount.update(role, currentCount   1)
      println(s"Playing $role")

    case ReportCount(role) =>
      sender ! messagesCount.getOrElse(role,0)

  }
}
case class Play(role: String)
case class ReportCount(role: String)
代码语言:javascript复制
import akka.actor._
import akka.util.Timeout
import akka.pattern.Patterns
import scala.concurrent.Await
import scala.concurrent.duration._

/**
  * Acotr模式是一种并发模型与另一种模型共享内存完全相反,Actor模型share nothing。
  * 所有线程(或进程)通过消息传递方式进行合作,这些线程(或进程)称为Actor,共享内存更适合单机多核的并发编程。
  */
object  UseActor extends App{
  val system = ActorSystem("sample")
  val depp = system.actorOf(Props[MessageActor])
  val hanks = system.actorOf(Props[MessageActor])
   /**
    *tell属于发了就完,什么都不管的类型。
    *
    */
  depp ! Play("Depp1")
  hanks ! Play("Hanks1")

  depp ! Play("Depp1")
  depp ! Play("Depp2")


  println("Sent roles to play ")
  /**
    * 询问(ask ?)模式,因为发送一条消息并等待响应可能会导致潜在的活锁
    * 消息可能永远不会到达,设置超时时间
    */
  implicit val timeout: Timeout = Timeout(2.seconds)
  val depp1 = Patterns.ask(depp, ReportCount("Depp1"), timeout)
  val depp2 = Patterns.ask(depp, ReportCount("Depp2"), timeout)
  val hanks1 = Patterns.ask(hanks, ReportCount("Hanks1"), timeout)

  val depp1Count = Await.result(depp1, timeout.duration)
  val depp2Count = Await.result(depp2, timeout.duration)
  val hanks1Count = Await.result(hanks1, timeout.duration)

  println(s"Depp played Depp1 $depp1Count time(s)")
  println(s"Depp played Depp2 $depp2Count time(s)")
  println(s"Hanks played Hanks1 $hanks1Count time(s)")

  val terminateFuture = system.terminate()
  Await.ready(terminateFuture, Duration.Inf)
}

结果:

Playing Depp1 Playing Hanks1 Sent roles to play  Playing Depp1 Playing Depp2 Depp played Depp1 2 time(s) Depp played Depp2 1 time(s) Hanks played Hanks1 1 time(s)

参考《Scala实用指南》

0 人点赞