1. 程式人生 > >Scala Actor的併發程式設計

Scala Actor的併發程式設計

1.什麼是Scala Actor

概念 Scala中的Actor能夠實現並行程式設計的強大功能,它是基於事件模型的併發機制,Scala是運用訊息(massage)的傳送,接收來實現多執行緒的,使用Scala能夠更能夠地實現多執行緒應用的開發。

2.1傳統java併發程式設計與Scala Actor程式設計的區別

'

2.2 對於Java,它的多執行緒實現需要對共享資源(變數,物件等)使用synchronized關鍵字進行程式碼塊同步,物件鎖互斥等等,而且,常常一大塊的try。。。catch語句塊中加上wait方法,notify方法,notifyAll方法是讓人很頭疼的,原因在於Java中對數使用的是可變狀態的物件資源,對這些資源進行共享來實現多執行緒編碼的話,控制好資源競爭與防止物件狀態被意外修改是非常重要的,而物件的不變性也是較難以保證的,而在Scala中,我們可以賦值不可變狀態的資源(即物件,Scala中一切都是物件,連函式,方法也是)的一個副本,再基於Actor的訊息傳送,接收機制並行程式設計

2.3.Actor方法執行順序 

1.首先呼叫start()方法啟動Actor

2.呼叫start()方法後其act()方法會被執行 

3.向Actor傳送訊息 

 2.4.傳送訊息的方式

3. Actor實戰   例項一

package practice
import scala.actors.Actor
object MyActor1 extends Actor{
  override def act(): Unit = {
    for (i<- 1 to 10){
      println("actor" +i)
      Thread.sleep(2000)
    }
  }
}
object MyActor2 extends Actor{
  override def act(): Unit = {
    for ( i <- 1 to 10 ){
      println("actor-2" +i)
      Thread.sleep(2000)
    }
  }
}
object ActotTest extends App{
  MyActor1.start()
  MyActor2.start()

說明:上面分別呼叫兩個單例物件的start()方法,他們的act()方法會被執行,相同與在java中開啟兩個執行緒,執行緒的run() 方法會被執行 

 注意:這兩個Actor是並行的執行的,act() 方法中的for迴圈執行完成後actor程式就退出了

-------------------------------------------------------------------------------------------------------------------

第二個例項(可以不斷地接收訊息)

package practice
//自己給自己傳送訊息
import scala.actors.Actor
class MyActor extends Actor{
  override def act(): Unit = {
    while (true){
      receive{
        case "start" =>{
          println("starting.....")
         Thread.sleep(5000)
          println("started")
        }
        case "stop" =>{
          println("stoping ....")
         Thread.sleep(5000)
          println("stopped")
        }
      }
    }
  }
}
object MyActor {
  def main(args: Array[String]): Unit = {
    val actor = new MyActor
    actor.start()
    actor ! "start"
    actor ! "stop"
    println("訊息傳送完成")
  }
}
import scala.actors.Actor
class MyActor extends Actor{
  override def act(): Unit = {
    while (true){
      receive{
        case "start" =>{
          println("starting.....")
         Thread.sleep(5000)
          println("started")
        }
        case "stop" =>{
          println("stoping ....")
         Thread.sleep(5000)
          println("stopped")
        }
      }
    }
  }
}
object MyActor {
  def main(args: Array[String]): Unit = {
    val actor = new MyActor
    actor.start()
    actor ! "start"
    actor ! "stop"
    println("訊息傳送完成")
  }
}

說明:在act()方法加入了while(true)迴圈,就可以不停的接收訊息 

注意:傳送start訊息和stop的訊息是非同步的,但是Actor接收到訊息執行的過程是同步的按順序執行

----------------------------------------------------------------------------------------------------------

3.3 第三個例子(react 方式會複用執行緒,比receive更高效)

package practice
import scala.actors.Actor
class YourActor extends  Actor{
  override def act(): Unit = {
    loop{
      react{
        case "start" => {
          println("starting ...")
          Thread.sleep(5000)
          println("started")
        }
        case "stop" => {
          println("stopping ...")
          Thread.sleep(8000)
          println("stopped ...")
        }
      }
    }
  }
}


object YourActor {
  def main(args: Array[String]) {
    val actor = new YourActor
    actor.start()
    actor ! "start"
    actor ! "stop"
    println("訊息傳送完成!")
  }
}

說明:react 如果要反覆執行訊息出來,react外層要用loop,不能用while

3.4 第四個例子(結合case  class 傳送訊息)

package practice
import scala.actors.Actor
case class SyncMsg(id:Int,msg:String)
case class AsyncMsg(id:Int,msg:String)
case class ReplyMsg(id:Int,msg:String)

class AppleActor extends Actor{
  override def act(): Unit = {
    while (true){
      receive{
        case "start" => println("starting ....")
        case  SyncMsg(id,msg) =>{
          println(id+",sync"+msg)
          Thread.sleep(5000)
          sender !ReplyMsg(3,"finished")
        }
        case AsyncMsg(id,msg) =>{
          println(id +",astnc"+msg)
          Thread.sleep(5000)
        }
      }
    }
  }
}
object AppleActor{
  def main(args: Array[String]): Unit = {
    val a=new AppleActor
    a.start()
    //非同步訊息
    a ! AsyncMsg(1,"hello actor")
    println("非同步訊息傳送完成")
    //同步訊息
    val reply= a !! SyncMsg(2 ,"hello actor")
    println(reply.isSet)
    val c=reply.apply()
    println(reply.isSet)
    println(c)
  }
}