1 Creating Actors
2 Sending and Receiving Messages
3 Working with Multiple Actors
4 Coordinating Actors
5 Using Typed Actors
6 Typed Actors and Murmurs
7 Mixing Actors and STM
8 Using Transactors
9 Coordinating Typed Actors
10 Remote Actors
11 Limitations of the Actor-Based Model
12 epliogue
Life cycle of an actor
We have quite a few choices of actor libraries to pick from. But Scala conciseness and idioms shine in the Akka API. At the same time, they have dont quite a wonderful job of exposing(暴露) a traditional Java API so we can easily create and use actors in Java code.
Creating Actors in Java
Akka’s abstract class akka.actor.UntypedActor represents an actor. Simply extend this and implement the required onReceive() method–this method is called whenever a message arrives for the actor. Let’s give it a shot. We will create an actor… how about a HollywoodActor that’ll respond to requests to play different roles?
import akka.actor.UntypedActor;
@SuppressWarnings("unchecked")
public class HollywoodActor extends UntypedActor {
public void onReceive(final Object role) {
System.out.println("Playing " + role +
" from Thread " + Thread.currentThread().getName());
}
}
The onReceive() method takes an Object as a parameter. In this example, we are simply printing it out along with the details of the thread that is processing the message.
Action
public class UseHollywoodActor{
public static void main(final String[] args) throws InterruptedException{
final ActorRef johnnyDepp = Actors.actorOf(HollywoodActor.class).start();
johnnyDepp.sendOneWay("Jack Sparrow");
Thread.sleep(100);
johnnyDepp.sendOneWay("Edward Scissorhands");
Thread.sleep(100);
johnnyDepp.sendOneWay("Willy Wonka");
Actors.registry().shutdownAll();
}
}
In Java we’d generally create objects using new, but Akka actors are not simple objects–they are active objects. So , we create them using a special method actorOf(). Alternately, we could create an instance using new and wrap it around a call to actorOf() to get an actor reference. Start it by calling the start() method. When we start an actor, Akka puts it into a registry; the actor is accessible through the registry untill the actor is stopped. In the example, now johnnyDepp, of type ActorRef, is a reference to our actor instance.
//解释:
2016年10月20日 - 華納將拍攝《巧克力冒險工廠》廠主威利旺卡個人電影 … Factory)由提姆·波頓(Tim Burton)執導,強尼·戴普(Johnny Depp)出演威利·旺卡(Willy Wonka)一角。
Next we send a few messages to the actor with roles to play using the sendOneWay() method. Once a message is sent, we really do not have to wait. However, in this case, the delay will help us learn one more detail, which is how actors switch threads, as we’ll see soon. In the end, we ask to close down all running actors. Instead of calling the** shutdownAll() method**, we may call the stop() method on individual actors **or **send them a kill message as well.
运行配置
javac -d . -classpath $AKKA_JARS HollywoodActor.java UseHollywoodActor.java
java -classpath $AKKA_JARS com.agiledeveloper.pcj.UseHollywoodActor
//前提要设置classpath
export AKKA_JARS="$AKKA_HOME/lib/scala-library.jar:\
$AKKA_HOME/lib/akka/akka-stm-1.1.3.jar:\
$AKKA_HOME/lib/akka/akka-actor-1.1.3.jar:\
$AKKA_HOME/lib/akka/multiverse-alpha-0.6.2.jar:\
$AKKA_HOME/lib/akka/akka-typed-actor-1.1.3.jar:\
$AKKA_HOME/lib/akka/aspectwerkz-2.2.3.jar:\
$AKKA_HOME/config:\
."
结果
format: Playing ** from Thread **
Playing Jack Sparrow from Thread akka:event-driven:dispatcher:global-1
Playing Edward Scissorhands from Thread akka:event-driven:dispatcher:global-2
Playing Willy Wonka from Thread akka:event-driven:dispatcher:global-3
结论:
In any case only one message will be handled at any time. The key point is that the actors are single-threaded but don’t hold their threads hostage(不会一直占有). They gracefully release their threads when they wait for a message; the delay we added helped introduce this wait and illustrate this point.
创建Actor–send parameters during actor creation
import akka.actor.UntypedActor;
@SuppressWarnings("unchecked")
public class HollywoodActor extends UntypedActor {
private final String name;
public HollywoodActor(final String theName) { name = theName; }
public void onReceive(final Object role) {
if(role instanceof String)
System.out.println(String.format("%s playing %s", name, role));
else
//无法识别的类型 可以发送error code,logging etc.
System.out.println(name + " plays no " + role);
}
}
启动
import akka.actor.UntypedActorFactory;
import akka.actor.UntypedActor;
import akka.actor.ActorRef;
import akka.actor.Actors;
public class UseHollywoodActor {
public static void main(final String[] args) throws InterruptedException {
//匿名内部类使用,不需要单独定义
final ActorRef tomHanks = Actors.actorOf(new UntypedActorFactory() {
public UntypedActor create() { return new HollywoodActor("Hanks"); }
}).start();
tomHanks.sendOneWay("James Lovell");
tomHanks.sendOneWay(new StringBuilder("Politics"));
tomHanks.sendOneWay("Forrest Gump");
Thread.sleep(1000);//关闭之前,有时间回应
tomHanks.stop();
}
}
//注意:We communicate with actors by sending messages and not by invoking methods directly.
The subsequentcall to actorOf() turns the regular object that extends from UntypedActor into an Akka actor.
结果
Hanks playing James Lovell
Hanks plays no Politics
Hanks playing Forrest Gump
Scala 语法–> 变量名 : 类型
class HollywoodActor(val name : String) extends Actor {
def receive = {
case role : String => println(String.format("%s playing %s", name, role))
case msg => println(name + " plays no " + msg)
}
}