Scala系列學習七 Actor
阿新 • • 發佈:2018-12-12
Scala中的Actor能夠實現並行程式設計的強大功能,它是基於事件模型的併發機制,Scala是運用訊息(message)的傳送、接收來實現多執行緒的。使用Scala能夠更容易地實現多執行緒應用的開發。
1.首先呼叫start()方法啟動Actor 2.呼叫start()方法後其act()方法會被執行 3.向Actor傳送訊息
! |
傳送非同步訊息,沒有返回值。 |
!? |
傳送同步訊息,等待返回值。 |
!! |
傳送非同步訊息,返回值是 Future[Any]。 |
1、初始Actor
object ActorDemo extends Actor { /** * Scala中的Actor能夠實現並行程式設計的強大功能, * 它是基於事件模型的併發機制,Scala是運用訊息(message)的傳送、接收來實現多執行緒的。 * 使用Scala能夠更容易地實現多執行緒應用的開發。 */ override def act(): Unit = { for (i <- 1 to 10) { println("actor-1" + i) Thread.sleep(1000) } } } object ActorDemo2 extends Actor { override def act(): Unit = { for (i <- 11 to 22) { println("actor-2" + i) Thread.sleep(1000) } } } object ActorRun1 extends App { //呼叫start來進行啟動兩個執行緒,與在java中的run方法是一樣的,這兩個執行緒會並行執行,act()方法中的for迴圈執行完成後actor程式就退出了 ActorDemo.start() ActorDemo2.start() }
2、繼承Actor類
//使用類進行多執行緒 class ActorDemo3 extends Actor { override def act(): Unit = { while (true) { receive { case "start" => { println("starting") Thread.sleep(5000) println("Started") } case "stop" => { println("stopping ...") Thread.sleep(5000) println("stopped ...") } } } } } object ActorRun2 extends App { /** * 使用while (true) 迴圈,不停的接收訊息 * 傳送start訊息和stop的訊息是非同步的, * Actor接收到訊息執行的過程是同步的按順序執行 */ private val actor = new ActorDemo3 actor.start() actor ! "start" actor ! "stop" println("訊息傳送結束") }
3、使用react複用執行緒
//使用react來進行執行緒複用,效率相較於recive要高
class ActorDemo4 extends Actor {
override def act(): Unit = {
loop {
//不在使用while,而是使用loop
react {
case "start" => {
println("starting")
Thread.sleep(5000)
println("Started")
}
case "stop" => {
println("stopping ...")
Thread.sleep(5000)
println("stopped ...")
}
}
}
}
}
object ActorRun4 extends App {
private val actor = new ActorDemo4
actor.start()
actor ! "start"
actor ! "stop"
println("訊息傳送結束")
}
4、使用case class
//使用case class 來進行訊息的傳送
case class SyncMsg(id: Int, msg: String)
case class AsyncMsg(id: Int, msg: String)
case class ReplyMsg(id: Int, msg: String)
class ActorDemo5 extends Actor {
override def act(): Unit = {
loop {
react {
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 + ",async " + msg)
Thread.sleep(5000)
}
}
}
}
}
5、非同步同步訊息傳送
object ActorRun5 extends App {
private val actor = new ActorDemo5
actor.start()
//非同步訊息
actor ! AsyncMsg(1, "hello actor")
println("非同步訊息傳送完成")
//同步訊息
// 預設情況下,訊息都是非同步的;但是如果希望傳送的訊息是同步的,即對方接受後,一定要給自己返回結果,那麼可以使用!?的方式傳送訊息。即val reply = actor !? message。
//val content = a.!?(1000, SyncMsg(2, "hello actor"))
//println(content)
//如果要非同步傳送一個訊息,但是在後續要獲得訊息的返回值,那麼可以使用Future。即!!語法。val future = actor !! message。val reply = future()。
val reply = actor !! SyncMsg(2, "hello actor")
println(reply.isSet)
//println("123")
val c = reply.apply()
println(reply.isSet)
println(c)
}