package com.ibm.jactors.test;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.ibm.jactors.Actor;
import com.ibm.jactors.DefaultActorManager;
import com.ibm.jactors.DefaultMessage;
import com.ibm.jactors.Message;
/**
* An actor that sends messages while counting down a send count.
*
* @author BFEIGENB
*
*/
public class TestActor extends TestableActor {
@Override
public void activate() {
logger.trace("TestActor activate: %s", this);
super.activate();
}
@Override
public void deactivate() {
logger.trace("TestActor deactivate: %s", this);
super.deactivate();
}
// runBody 方法是在收到任何消息之前、首次创建 actor 的时候调用的。它通常用于将第一批消息引导至 actor
@Override
protected void runBody() {
// logger.trace("TestActor:%s runBody: %s", getName(), this);
DefaultActorTest.sleeper(1);
DefaultMessage m = new DefaultMessage("init", 8);
getManager().send(m, null, this);
}
// 在 actor 即将收到消息时调用;这里 actor 可拒绝或接受消息
@Override
protected Message testMessage(){
return super.testMessage();
}
// 在 actor 收到一条消息时调用。在通过较短延迟来模拟某种一般性处理之后,才开始处理该消息
@Override
protected void loopBody(Message m) {
// logger.trace("TestActor:%s loopBody %s: %s", getName(), m, this);
DefaultActorTest.sleeper(1);
String subject = m.getSubject();
// 如果消息为 “repeat”,那么 actor 基于 count 参数开始发送另外 N-1 条消息。
// 这些消息通过调用 actor 管理器的 send 方法发送给一个随机 actor
if ("repeat".equals(subject)) {
int count = (Integer) m.getData();
logger.trace("TestActor:%s repeat(%d) %s: %s", getName(), count, m, this);
if (count > 0) {
m = new DefaultMessage("repeat", count - 1);
// logger.trace("TestActor loopBody send %s: %s", m, this);
String toName = "actor" + DefaultActorTest.nextInt(DefaultActorTest.TEST_ACTOR_COUNT);
Actor to = actorTest.getTestActors().get(toName);
if (to != null) {
getManager().send(m, this, to);
} else {
logger.warning("repeat:%s to is null: %s", getName(), toName);
}
}
} else if ("init".equals(subject)) {
// 如果消息为 “init”,那么 actor 通过向随机选择的 actor 或一个属于 common 类别的 actor 发送两组消息,启动 repeat 消息队列。
int count = (Integer) m.getData();
count = DefaultActorTest.nextInt(count) + 1;
logger.trace("TestActor:%s init(%d): %s", getName(), count, this);
for (int i = 0; i < count; i++) {
DefaultActorTest.sleeper(1);
m = new DefaultMessage("repeat", count);
// logger.trace("TestActor runBody send %s: %s", m, this);
String toName = "actor" + DefaultActorTest.nextInt(DefaultActorTest.TEST_ACTOR_COUNT);
Actor to = actorTest.getTestActors().get(toName);
if (to != null) {
getManager().send(m, this, to);
} else {
logger.warning("init:%s to is null: %s", getName(), toName);
}
DefaultMessage dm = new DefaultMessage("repeat", count);
dm.setDelayUntil(new Date().getTime() + (DefaultActorTest.nextInt(5) + 1) * 1000);
getManager().send(dm, this, this.getClass().getSimpleName());
}
} else {
logger.warning("TestActor:%s loopBody unknown subject: %s", getName(), subject);
}
}
public static void main(String[] args) {
// 在 common 类别中创建了 2 个 actor,在 default 类别中创建了 5 个 actor,然后启动它们
DefaultActorManager am = DefaultActorManager.getDefaultInstance();
Map<String, Actor> testActors = new HashMap<String, Actor>();
for (int i = 0; i < 2; i++) {
Actor a = am.createActor(TestActor.class, "common" + i);
a.setCategory("common");
testActors.put(a.getName(), a);
}
for (int i = 0; i < 5; i++) {
Actor a = am.createActor(TestActor.class, "actor" + i);
testActors.put(a.getName(), a);
}
for (String key : testActors.keySet()) {
am.startActor(testActors.get(key));
}
for (int i = 120; i > 0; i--) {
if (i < 10 || i % 10 == 0) {
System.out.printf("main waiting: %d...%n", i);
}
DefaultActorTest.sleeper(1);
}
am.terminateAndWait();
}
}