在瞭解了Scala的一些基本特性之後,看到了它的線程實現:Actor。筆者不知道這麼叫是否合適,因為Actor的目的似乎專註於在實體之間使用訊息傳遞來協作。翻了一下它的原型定義如下:
abstract class Actor extends Thread with MailBox{def act() : Unitoverride def run(): Unit = act()def !(msg: Any) = send(msg)}
從這個版本的源碼(<=Scala 2.7)中可以看出,Actor除了代表線程類之外還引入了MailBox,本來我們都知道繼承java.lang.Thread只會要求重寫run()方法,不會有別的改變,Scala使用act()來代替了使用run()的習慣,由於混入了MailBox使得Scala的Actor具有了receive和receiveWith等新的方法,從而完成訊息傳遞的協作。(但筆者最近在新的Scala版本中發現這一切都有了重大改變,Actor不再混入MailBox,整個Actor只包含了伴生對象object
Actor和抽象介面trait Actor的定義,看起來線程實現的角色更加簡潔明了。receive和receiveWithIn被同時直接加入為伴生對象Actor和trait Actor中。)
這裡不深入討論Actor的特點,先通過一個小例子,來看Actor是如何工作的:
import scala.actors.Actor, java.util._abstract class AuctionMessagecase class Offer(bid: Int, client: Actor) extends AuctionMessagecase class Inquire(client: Actor) extends AuctionMessagecase object TIMEOUTabstract class AuctionReplycase class Status(asked: Int, expire: Date) extends AuctionReplycase object BestOffer extends AuctionReplycase class BeatenOffer(maxBid: Int) extends AuctionReplycase class AuctionConcluded(seller: Actor, client: Actor) extends AuctionReplycase object AuctionFailed extends AuctionReplycase object AuctionOver extends AuctionReply/*** Before finally stopping, it stays active for another period determined by the* timeToShutdown constant and replies to further offers that the auction is closed**/class Auction (seller: Actor, minBid: Int, closing: Date) extends Actor{// 60 minutes to shut down the auctionval timeToShutdown = 3600000// minimum bid for each offerval bidIncrement = 10def act(){var maxBid = minBid - bidIncrementvar maxBidder: Actor = nullvar running = truewhile(running){//receiveWithin: just span a period of time for mailbox messages then stoppedreceiveWithin ((closing.getTime() - new Date().getTime())){case Offer(bid, client) =>if(bid >= maxBid + bidIncrement){//beat successfully, notify the current maxBidder, then replace itif(maxBid >= minBid) maxBidder ! BeatenOffer(bid)//reply to client the current offer peak valuemaxBid = bid;maxBidder = client; client ! BestOffer}else{//beat failed, return the current max bid value to offer clientclient ! BeatenOffer(maxBid)}case Inquire(client) =>// query the max bid and closing timeclient ! Status(maxBid, closing)case TIMEOUT =>//auction doneif(maxBid >= minBid){val reply = AuctionConcluded(seller, maxBidder)maxBidder ! reply; seller ! reply}else{//no one get the auction, notify sellerseller ! AuctionFailed}//for further offer message, tell them overreceiveWithin(timeToShutdown){case Offer(_, client) => client ! AuctionOvercase TIMEOUT => running = false}}}}}
這是一個拍賣通訊的例子,在while迴圈裡Auction能分辨請求訊息的種類然後做合適的處理,當發生逾時事件,開始進行整個結束流程。