zoukankan      html  css  js  c++  java
  • Classic Actor | Become/Unbecome

    AKKa支持在runtime时hotswapped (热插拔)Actor的message loop:在Actor中调用context.become方法。hotswapped的代码被存在一个栈中,可以被pushed(replacing 或 adding 在顶部)和popped。become一个特别好的例子是用它来实现一个有限状态机(FSM)。 Become/Unbecome特性很方便去实现有限状态转换机。

    需要注意的是,当actor被它的Supervisor重新启动时,它将重置为原始行为。[1]

    import akka.actor.AbstractActor;
    import akka.actor.Props;
    import akka.event.Logging;
    import akka.event.LoggingAdapter;
    public class RequestActor6 extends AbstractActor {
        protected final String name;
        protected final LoggingAdapter log = Logging.getLogger(context().system(), this);
        private Receive hiHandler;
        private Receive helloHandler;
        public RequestActor6(String name) {
            this.name = name;
            hiHandler = receiveBuilder().matchEquals("Hi", message - >{
                log.info(message);
                getContext().become(helloHandler);
            }).matchAny(message - >{
                log.error(message.toString());
            }).build();
            helloHandler = receiveBuilder().matchEquals("Hello", message - >{
                log.info(message);
                getContext().become(hiHandler);
            }).matchAny(message - >{
                log.error(message.toString());
            }).build();
        }
        public static Props props(String name) {
            return Props.create(RequestActor6.class, name);
        }
        @Override public Receive createReceive() {
            return receiveBuilder().match(String.class, message - >{
                log.info(message);
                getContext().become(helloHandler);
            }).build();
        }
    }
    
    import akka.actor.ActorRef;
    import akka.actor.ActorSystem;
    import akka.testkit.TestActorRef;
    import org.junit.jupiter.api.Test;
    class RequestActor6Test {
        ActorSystem system = ActorSystem.create();
        @Test public void test() {
            TestActorRef < RequestActor6 > ref = TestActorRef.create(system, RequestActor6.props("request6"));
            ref.tell("init", ActorRef.noSender()); //info init
            ref.tell("Hello", ActorRef.noSender()); //info Hello
            ref.tell("Hi", ActorRef.noSender()); //info Hi
            ref.tell("Hello", ActorRef.noSender()); //info Hello
            ref.tell("Hi", ActorRef.noSender()); //info Hi
            ref.tell("Hello", ActorRef.noSender()); //info Hello
            ref.tell("Hello", ActorRef.noSender()); //error Hello
        }
    }
    
    

    上面例子展示的是通过replace策略来替换栈头的handle,除此外还能通过pop(即 unbecom)策略移除当前handle切换上一个handle,在pop策略下需要保证"push"和“pop”操作次数要相等,否则会引起内存泄漏。

    import akka.actor.AbstractActor;
    import akka.actor.Props;
    import akka.event.Logging;
    import akka.event.LoggingAdapter;
    public class RequestActorUnbecome extends AbstractActor {
        protected final String name;
        protected final LoggingAdapter log = Logging.getLogger(context().system(), this);
        private AbstractActor.Receive hiHandler;
        private AbstractActor.Receive helloHandler;
        public RequestActorUnbecome(String name) {
            this.name = name;
            hiHandler = receiveBuilder().matchEquals("Hi", message - >{
                log.info(message);
                getContext().unbecome(); //切换到上一个handle
            }).matchAny(message - >{
                log.error(message.toString());
            }).build();
            helloHandler = receiveBuilder().matchEquals("Hello", message - >{
                log.info(message);
                getContext().become(hiHandler, false);//采用“pop”策略
            }).matchAny(message - >{
                log.error(message.toString());
            }).build();
        }
        static Props props(String name) {
            return Props.create(RequestActorUnbecome.class, name);
        }
        @Override public Receive createReceive() {
            return receiveBuilder().matchEquals("init", message - >{
                log.info(message);
                getContext().become(helloHandler);
            }).build();
        }
    }
    
    import akka.actor.ActorRef;
    import akka.actor.ActorSystem;
    import akka.testkit.TestActorRef;
    import org.junit.jupiter.api.Test;
    class RequestActorUnbecomeTest {
        ActorSystem system = ActorSystem.create();
        @Test
        public void test() {
            TestActorRef<RequestActorUnbecome> actorRef = TestActorRef.create(system,RequestActorUnbecome.props("Request"));
            actorRef.tell("init", ActorRef.noSender());// info init
            actorRef.tell("Hello",ActorRef.noSender());//info Hello
            actorRef.tell("Hi",ActorRef.noSender());//info Hi
            actorRef.tell("Hello",ActorRef.noSender());//info Hello
            actorRef.tell("Hello",ActorRef.noSender());//error Hello
            actorRef.tell("Hi",ActorRef.noSender());//info Hi
        }
    
  • 相关阅读:
    jvm基本结构和解析
    多态的意思
    java中对象的简单解读
    double类型和int类型的区别
    python 解析xml文件
    win10不能映射Ubuntu共享文件
    Qt程序打包
    Ubuntu boot分区文件误删,系统无法启动,怎么解
    ubuntu Boot空间不够问题“The volume boot has only 5.1MB disk space remaining”
    Ubuntu 分辨率更改 xrandr Failed to get size of gamma for output default
  • 原文地址:https://www.cnblogs.com/jj81/p/13970362.html
Copyright © 2011-2022 走看看