• 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
        }
    
  • 相关阅读:
    哪怕我变成一个庸俗女子
    硬盘接口的种类
    HTTPS与SHTTP
    Jquery动态加载页面
    iText简介
    TFS offline issue
    VS2008 调试慢的问题
    One error related to msxml4.dll (0x800C0014)
    46 Run Commands for Frequently Used Areas of Your Windows Computer
    快速启动工具入门——以Launchy为例(二)
  • 原文地址:https://www.cnblogs.com/jj81/p/13970362.html
Copyright © 2020-2023  润新知