在了解了Scala的一些基本特性之后,看到了它的线程实现:Actor。笔者不知道这么叫是否合适,因为Actor的目的似乎专注于在实体之间使用消息传递来协作。翻了一下它的原型定义如下:
abstract class Actor extends Thread with MailBox{ def act() : Unit override 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 AuctionMessage case class Offer(bid: Int, client: Actor) extends AuctionMessage case class Inquire(client: Actor) extends AuctionMessage case object TIMEOUT abstract class AuctionReply case class Status(asked: Int, expire: Date) extends AuctionReply case object BestOffer extends AuctionReply case class BeatenOffer(maxBid: Int) extends AuctionReply case class AuctionConcluded(seller: Actor, client: Actor) extends AuctionReply case object AuctionFailed extends AuctionReply case 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 auction val timeToShutdown = 3600000 // minimum bid for each offer val bidIncrement = 10 def act(){ var maxBid = minBid - bidIncrement var maxBidder: Actor = null var running = true while(running){ //receiveWithin: just span a period of time for mailbox messages then stopped receiveWithin ((closing.getTime() - new Date().getTime())){ case Offer(bid, client) => if(bid >= maxBid + bidIncrement){ //beat successfully, notify the current maxBidder, then replace it if(maxBid >= minBid) maxBidder ! BeatenOffer(bid) //reply to client the current offer peak value maxBid = bid; maxBidder = client; client ! BestOffer }else{ //beat failed, return the current max bid value to offer client client ! BeatenOffer(maxBid) } case Inquire(client) => // query the max bid and closing time client ! Status(maxBid, closing) case TIMEOUT => //auction done if(maxBid >= minBid){ val reply = AuctionConcluded(seller, maxBidder) maxBidder ! reply; seller ! reply }else{ //no one get the auction, notify seller seller ! AuctionFailed } //for further offer message, tell them over receiveWithin(timeToShutdown){ case Offer(_, client) => client ! AuctionOver case TIMEOUT => running = false } } } } }
这是一个拍卖通信的例子,在while循环里Auction能分辨请求消息的种类然后做合适的处理,当发生超时事件,开始进行整个结束流程。