Blocking calls in Akka Actors

前端 未结 3 507
旧巷少年郎
旧巷少年郎 2020-12-23 14:33

As a newbie, I am trying to understand how actors work. And, from the documentation, I think I understand that actors are objects which gets executed in sync mode and also t

3条回答
  •  滥情空心
    2020-12-23 15:07

    Really great intro "The Neophyte's Guide to Scala Part 14: The Actor Approach to Concurrency" http://danielwestheide.com/blog/2013/02/27/the-neophytes-guide-to-scala-part-14-the-actor-approach-to-concurrency.html.

    Actor receives message, wraps blocking code to future, in it's Future.onSuccess method - sends out results using other async messages. But beware that sender variable could change, so close it (make a local reference in the future object).

    p.s.: The Neophyte's Guide to Scala - really great book.

    Updated: (added sample code)

    We have worker and manager. Manager sets work to be done, worker reports "got it" and starts long process ( sleep 1000 ). Meanwhile system pings manager with messages "alive" and manager pings worker with them. When work done - worker notifies manager on it.

    NB: execution of sleep 1000 done in imported "default/global" thread pool executor - you can get thread starvation. NB: val commander = sender is needed to "close" a reference to original sender, cause when onSuccess will be executed - current sender within actor could be already set to some other 'sender' ...

    Log:

    01:35:12:632 Humming ...
    01:35:12:633 manager: flush sent
    01:35:12:633 worker: got command
    01:35:12:633 manager alive
    01:35:12:633 manager alive
    01:35:12:633 manager alive
    01:35:12:660 worker: started
    01:35:12:662 worker: alive
    01:35:12:662 manager: resource allocated
    01:35:12:662 worker: alive
    01:35:12:662 worker: alive
    01:35:13:661 worker: done
    01:35:13:663 manager: work is done
    01:35:17:633 Shutdown!
    

    Code:

    import akka.actor.{Props, ActorSystem, ActorRef, Actor}
    import com.typesafe.config.ConfigFactory
    import java.text.SimpleDateFormat
    import java.util.Date
    import scala.concurrent._
    import ExecutionContext.Implicits.global
    
    object Sample {
    
      private val fmt = new SimpleDateFormat("HH:mm:ss:SSS")
    
      def printWithTime(msg: String) = {
        println(fmt.format(new Date()) + " " + msg)
      }
    
      class WorkerActor extends Actor {
        protected def receive = {
          case "now" =>
            val commander = sender
            printWithTime("worker: got command")
            future {
              printWithTime("worker: started")
              Thread.sleep(1000)
              printWithTime("worker: done")
            }(ExecutionContext.Implicits.global) onSuccess {
              // here commander = original sender who requested the start of the future
              case _ => commander ! "done" 
            }
            commander ! "working"
          case "alive?" =>
            printWithTime("worker: alive")
        }
      }
    
      class ManagerActor(worker: ActorRef) extends Actor {
        protected def receive = {
          case "do" =>
            worker ! "now"
            printWithTime("manager: flush sent")
          case "working" =>
            printWithTime("manager: resource allocated")
          case "done" =>
            printWithTime("manager: work is done")
          case "alive?" =>
            printWithTime("manager alive")
            worker ! "alive?"
        }
      }
    
      def main(args: Array[String]) {
    
        val config = ConfigFactory.parseString("" +
          "akka.loglevel=DEBUG\n" +
          "akka.debug.lifecycle=on\n" +
          "akka.debug.receive=on\n" +
          "akka.debug.event-stream=on\n" +
          "akka.debug.unhandled=on\n" +
          ""
        )
    
        val system = ActorSystem("mine", config)
        val actor1 = system.actorOf(Props[WorkerActor], "worker")
        val actor2 = system.actorOf(Props(new ManagerActor(actor1)), "manager")
    
        actor2 ! "do"
        actor2 ! "alive?"
        actor2 ! "alive?"
        actor2 ! "alive?"
    
        printWithTime("Humming ...")
        Thread.sleep(5000)
        printWithTime("Shutdown!")
        system.shutdown()
    
      }
    }
    

提交回复
热议问题