diễn viên xử lý một thông điệp tại một thời điểm. Các mô hình cổ điển để xử lý nhiều thông điệp là có một diễn viên điều phối viên phía trước cho một nhóm các diễn viên tiêu dùng. Nếu bạn sử dụng phản ứng thì hồ bơi tiêu dùng có thể lớn nhưng sẽ chỉ sử dụng một số lượng nhỏ các luồng JVM. Đây là một ví dụ mà tôi tạo ra một nhóm gồm 10 người tiêu dùng và một điều phối viên ở phía trước cho họ.
import scala.actors.Actor
import scala.actors.Actor._
case class Request(sender : Actor, payload : String)
case class Ready(sender : Actor)
case class Result(result : String)
case object Stop
def consumer(n : Int) = actor {
loop {
react {
case Ready(sender) =>
sender ! Ready(self)
case Request(sender, payload) =>
println("request to consumer " + n + " with " + payload)
// some silly computation so the process takes awhile
val result = ((payload + payload + payload) map {case '0' => 'X'; case '1' => "-"; case c => c}).mkString
sender ! Result(result)
println("consumer " + n + " is done processing " + result)
case Stop => exit
}
}
}
// a pool of 10 consumers
val consumers = for (n <- 0 to 10) yield consumer(n)
val coordinator = actor {
loop {
react {
case msg @ Request(sender, payload) =>
consumers foreach {_ ! Ready(self)}
react {
// send the request to the first available consumer
case Ready(consumer) => consumer ! msg
}
case Stop =>
consumers foreach {_ ! Stop}
exit
}
}
}
// a little test loop - note that it's not doing anything with the results or telling the coordinator to stop
for (i <- 0 to 1000) coordinator ! Request(self, i.toString)
Mã này kiểm tra xem người tiêu dùng nào có sẵn và gửi yêu cầu đến người tiêu dùng đó. Các giải pháp thay thế chỉ được gán ngẫu nhiên cho người tiêu dùng hoặc sử dụng một bộ lập lịch vòng tròn.
Tùy thuộc vào những gì bạn đang làm, bạn có thể được phục vụ tốt hơn với tương lai của Scala. Ví dụ: nếu bạn không thực sự cần diễn viên thì tất cả các máy móc ở trên có thể được viết là
import scala.actors.Futures._
def transform(payload : String) = {
val result = ((payload + payload + payload) map {case '0' => 'X'; case '1' => "-"; case c => c}).mkString
println("transformed " + payload + " to " + result)
result
}
val results = for (i <- 0 to 1000) yield future(transform(i.toString))
Nguồn
2009-06-17 17:41:26
Tôi thực sự không thấy câu hỏi này biện minh cho việc giảm giá. Nếu tôi có thể đọc toàn bộ một chương về các diễn viên trong Lập trình ở Scala và không chắc chắn về câu trả lời, đó là một câu hỏi hoàn toàn hợp lệ. –
Một diễn viên duy nhất xử lý các thông điệp tuần tự bởi vì ý tưởng là người dùng có thể sử dụng một tác nhân để dàn xếp quyền truy cập vào một tài nguyên được chia sẻ (nếu không) và không cần đồng bộ hóa khác trên tài nguyên được chia sẻ.Nếu thông báo có thể được xử lý tuần tự, bạn cần sử dụng các khóa bên trong các tác nhân của mình để đảm bảo rằng các lỗi đồng bộ hóa không thể xảy ra. –