Scala学习笔记(三)Actor简单例子

在了解了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能分辨请求消息的种类然后做合适的处理,当发生超时事件,开始进行整个结束流程。

你可能感兴趣的:(Scala学习笔记(三)Actor简单例子)