• 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
        }
    
  • 相关阅读:
    PAT 甲级 1115 Counting Nodes in a BST (30 分)
    PAT 甲级 1114 Family Property (25 分)
    PAT 甲级 1114 Family Property (25 分)
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
  • 原文地址:https://www.cnblogs.com/jj81/p/13970362.html
Copyright © 2020-2023  润新知