scala系列--併發01

  最近研究了一些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().雙向通信不是一個好主意。“發送並忘記”(!)模型好得多。

示例:

統計字符串的次數。

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)
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實用指南》

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章