询问模式:Actor中的Future
与同步方法不同,在发送异步消息后,接受消息的Actor可能根本来不及处理你的消息,调用方就已经返回了,和Future模式不同的是,在传统的异步调用中,我们进行的是函数调用,但在这里,我们发送了一条消息。
printer Actor
public class Printer extends UntypedAbstractActor {
@Override
public void onReceive(Object message) throws Throwable {
if(message instanceof Integer){
System.out.println("Printer:"+message);
}else {
unhandled(message);
}
}
}
Woker Actor
public class Worker extends UntypedAbstractActor {
@Override
public void onReceive(Object message) throws Throwable {
if (message instanceof Integer) {
Thread.sleep(1000);
int i = Integer.parseInt(message.toString());
getSender().tell(i*i, getSelf());
} else {
unhandled(message);
}
}
public static void main(String[] args) throws TimeoutException, InterruptedException {
ActorSystem system=ActorSystem.create("askdemo");
ActorRef a=system.actorOf(Props.create(Worker.class),"worker");
ActorRef b=system.actorOf(Props.create(Printer.class),"printer");
Future<Object> f= Patterns.ask(a,5,1000);
int re= (int) Await.result(f,Duration.create(6,TimeUnit.SECONDS));
System.out.println("result:"+re);
Future<Object> future1 = Patterns.ask(a, 8, 1000);
Patterns.pipe(future1, system.dispatcher()).to(b);
a.tell(PoisonPill.getInstance(), ActorRef.noSender());
}
}
多个Actor同时修改数据:Agent
在Akka中,使用一种叫做Agent的组件来实现多个Actor访问同一个变量。当一个Actor希望改变Agent的值时,它会向Agent下发一个动作(action)。当多个Actor同时改变Agent时,这些action将会在ExecutionContext中被并发调度执行。在任意时刻,一个Agent最多只能执行一个action,对于某一个线程来说,它执行action的顺序与它的发生顺序一致,但对于不同线程来说,这些action可能会交织在一起。
Agent的修改可以使用两种方式:send和alter,区别就在于send方法没有返回值,而alter方法会返回一个Future对象。
public class CounterActor extends UntypedAbstractActor {
public class AgentDemo{
public static Agent<Integer> counterAgent=Agent.create(0, ExecutionContexts.global());
static ConcurrentLinkedQueue<Future<Integer>> futures=new ConcurrentLinkedQueue<>();
}
Mapper addMapper=new Mapper<Integer,Integer>(){
@Override
public Integer apply(Integer parameter) {
return parameter+1;
}
};
@Override
public void onReceive(Object message) throws Throwable {
if(message instanceof Integer){
for (int i = 0; i < 10000; i++) {
Future<Integer> f=AgentDemo.counterAgent.alter(addMapper);
AgentDemo.futures.add(f);
}
getContext().stop(getSelf());
}else{
unhandled(message);
}
}
public static void main(String[] args) {
ActorSystem system=ActorSystem.create();
ActorRef[] counter=new ActorRef[10];
for (int i = 0; i <counter.length ; i++) {
counter[i]=system.actorOf(Props.create(CounterActor.class),"counter_"+i);
}
Inbox inbox =Inbox.create(system);
for (int i = 0; i < counter.length; i++) {
inbox.send(counter[i],1);
inbox.watch(counter[i]);
}
int closeCount=0;
while (true){
Object msg=inbox.receive(Duration.create(1,TimeUnit.SECONDS));
if(msg instanceof Terminated){
closeCount++;
if(closeCount==counter.length){
break;;
}
}else{
System.out.println(msg);
}
}
//等待所有的累加线程完成
Futures.sequence(futures,system.dispatcher()).onComplete(new OnComplete<Iterable<Object>>() {
@Override
public void onComplete(Throwable failure, Iterable<Object> success) throws Throwable {
System.out.println("counterAgent="+counterAgent.get());
system.shutdown();
}
},system.dispatcher());
}
}