Akka (1): Basic Introduction

Before we touch Akka, we should know what is Akka. Akka uses Actor model to provide a platform to build a correct concurrent and scalable applications. Here we notice two key words, one is concurrent, the other is scalable. (Here I haven’t think out a good example to explain it, leave it here, I will add more in the future…)

Actor model? So what is actor. We can treat actor as thread entity, which has a mailbox. Actor can be created by system.actorOf, use receive to obtain mailbox’s message, and ! to send message to mailbox. Actor is lighter than thread, because actor can re-use thread. One actor can take up multiple threads, one thread can be used by multiple actor. So there is 1 to 1 relationship between actor and thread, which depends on dispatcher. 

Following we just introduce very simply way to use Akka.

1. Concept

It is easy to define Actor by inheriting from akka.actor.Actor. You just need to implement receive method.

class Hello extends Actor {
  def receive = {
    case msg: String => println("hello " + msg)
    case _ => println("unexpected message.")
  }
}

2. Start

You can create Actor instance by ActorSystem.

val system = ActorSystem("hellosystem")
val hello = system.actorOf(Props[Hello], name = "hello")
val hello1 = system.actorOf(Props[Hello])
val hello2 = system.actorOf(Props(new Hello()))

If you want to create sub-Actor in a Actor, you can use internal ActorContext object.

context.actorOf(Props[children], name = "children")

If you want to create remote-Actor, you need to use actorSelection (actorFor is not used any more.)

context.actorSelection("akka.tcp://HelloRemoteSystem@127.0.0.1:5150/user/RemoteActor")

3. Send Message

It is quite simply to send message by “!“. You can send messages with any types which is asynchronous.

hello ! "bruce"
hello ! 10086

If you want to use synchronous, you need to use Future object.

implicit val timeout = Timeout(5 seconds)
val future = hello ? "sha"
val result = Await.result(future, timeout.duration).asInstanceOf[String]

4. Stop

There are two methods to stop a Actor. One is to use internal way by ActorContext.stop(), which will kills each children actor and finally kill itself.

def receive = {
  case "stop" => context.stop(self)
  ...
}

The other one is to use external method by ActorRef.tell(). The last parameter is to set whom is needed to reply to, if no needed, just send empty.

hello.tell(PoisonPill.getInstance, ActorRef.noSender);

5. Example

object HengHa extends App {
  val system = ActorSystem("HengHaSystem")
  val ha = system.actorOf(Props[Ha], name = "ha")
  val heng = system.actorOf(Props(new Heng(ha)), name = "heng")
  heng ! "start"
}
class Heng(ha:ActorRef) extends Actor {
  def receive = {
    case "start" => ha ! "heng"
    case "ha" => 
      println("ha")
      ha ! "heng"
    case _ => println("heng what?")
  }
}
class Ha extends Actor {
  def receive = {
    case "heng" =></p?
      println("heng")
      sender ! "ha"
    case _ => println("ha what?")
  }
}

Note: when an actor receives a message from another actor, it also receives an implicit reference named sender, and it can use that reference to send a message back to the originating actor.

When you make it running, it will print out:

heng
ha
heng
ha
heng

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s