2009-06-17 35 views
27

The reply cho câu hỏi gần đây của tôi cho biết rằng một diễn viên đã xử lý thông báo của mình từng thư một. Điều này có đúng không? Tôi thấy không có gì là rõ ràng nói rằng (trong Lập trình trong Scala), trong đó có chứa đoạn mã sau (tr. 593)Các diễn viên Scala có thể xử lý đồng thời nhiều thư không?

Nếu [phương pháp react] tìm thấy một thông điệp có thể được xử lý, [nó] sẽ lên lịch xử lý tin nhắn đó để thực hiện sau và ném một ngoại lệ

(Nhấn mạnh của riêng tôi). Hai câu hỏi có liên quan (và loại trừ lẫn nhau):

  1. Giả sử một diễn viên có thể xử lý nhiều thông điệp một cách tương tự, làm cách nào để buộc diễn viên xử lý tin nhắn 1 một lần (nếu đây là điều tôi muốn làm)? (Sử dụng receive?)
  2. Giả sử một diễn viên xử lý thông điệp cùng một lúc, làm thế nào tôi sẽ thực hiện tốt nhất là một diễn viên mà trong thực tế thể thông điệp quá trình đồng thời

chỉnh sửa: làm một chút thử nghiệm dường như phát hiện ra rằng tôi sai và các diễn viên đó thực sự là tuần tự. Vì vậy, đó là câu hỏi số 2 mà tôi cần trả lời

+5

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ệ. –

+0

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. –

Trả lời

26

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)) 
+0

Bạn có thể giải thích ý nghĩa của Ready? –

+0

Sẵn sàng trong ví dụ này là một trường hợp lớp hoạt động như một thông điệp để vượt qua. Điều phối viên gửi thông điệp Sẵn sàng cho người tiêu dùng về cơ bản có nghĩa là 'bạn đã sẵn sàng chưa?' và người tiêu dùng trả lời với một thông điệp sẵn sàng trở lại có nghĩa là 'có'. Người tiêu dùng đầu tiên phản hồi sau đó được chuyển yêu cầu. – harmanjd

0

Nếu bạn muốn làm nhiều việc thì bạn nên sử dụng nhiều diễn viên. Toàn bộ lý do để sử dụng diễn viên là phân chia công việc giữa nhiều quy trình độc lập.

+0

Đây là câu trả lời vô ích. Giả sử tôi có một diễn viên nào đó đọc các sự kiện được xử lý và gửi cho một số diễn viên khác để được xử lý. Ngoại trừ thực tế, nhiều sự kiện có thể được xử lý đồng thời, ngay cả khi mã xử lý thực tế giống hệt nhau (do đó tôi viết ở một nơi duy nhất, tức là trong 1 diễn viên). Làm cách nào để các diễn viên có thể "nhân rộng" (hoặc tạo ra một nhóm) các diễn viên (giống hệt) này để tôi có thể tận dụng tối đa tài nguyên lập trình của mình? –

+0

Tôi có nghĩa là "sử dụng tốt nhất tài nguyên bộ xử lý của tôi" –

+1

Câu trả lời của tôi không hữu ích vì câu hỏi của bạn không được đặt đúng khung. Một diễn viên là một quá trình không phải là một đoạn mã. Cũng giống như một đối tượng là một thể hiện của một lớp. Bạn đã không hỏi làm cách nào để tạo nhiều diễn viên để xử lý nhiều thư. Bạn muốn biết làm thế nào bạn có thể có được một diễn viên để xử lý nhiều tin nhắn cùng một lúc. Câu trả lời của tôi là một nỗ lực để làm rõ những gì tôi nhận thức là sự hiểu lầm của bạn về mô hình diễn viên. – mamboking

6

Tôi nghĩ rằng câu trả lời là một Actor không thể xử lý thư một cách không đồng bộ. Nếu bạn có một Actor cần được lắng nghe những thông điệp có những thông điệp có thể bị xử lý không đồng bộ, sau đó nó có thể được viết như thế này:

val actor_ = actor { 

    loop { 
    react { 
     case msg => 
     //create a new actor to execute the work. The framework can then 
     //manage the resources effectively 
     actor { 
      //do work here 
     } 
     } 
    } 
    } 
Các vấn đề liên quan