• Classic Actor | Stopping actor


    流程

        Stop 一个actor会有有两个步骤,首先actor会暂停其邮箱处理和发送stop command给所有children actors, 这一步骤会在stop children actors阶段持续,直到stop最后一个children actor才会进入下一个步骤,stop自己本身(调用postStop钩子函数,倾销mailbox,通知DeathWatch和supervisor)。 这两个步骤确保actor系统子树以有序的方式销毁,将停止(销毁)命令传播给叶子,并将它们的确认传回supervisor。如果其中一个actor没有响应(即处理消息的时间延长,因此没有收到停止命令),整个进程将被卡住。当完成stop 一个 actor后,会调用postStop()钩子函数,可以在postStop定义清理资源的动作。
    需要注意的是,stop actor实际上是异步执行的,在发出stop actor 命令时actor不会立即被销毁,所以在真正销毁之前会持续处理现有的消息,但mailbox的消息不会被处理 (e. stop may return before the actor is stopped.),mailbox中未消费的消息会默认发送到ActorSystem的deadLetters(可通过定义mailbox的实现改变规则)。[1]

    方法

    1.通过调用ActorRefFactory的stop方法来停止Actor, 例如使用ActorContext或ActorSystem(ActorContext是继承了ActorRefFactory 和ActorSystem是实现ActorRefFactory),通常ActorContext用来stopactor自己及子actor,而ActorSystem用来stop top-level的actors.

    2.通过向actor发送akka.actor.PoisonPill 消息,actor当消费到PoisonPill消息时开始执行stop流程。

    3.通过向actor发送akka.actor.Kill消息,与PoisonPill不同的是,Kill actor会抛出ActorKilledException,好处就是触发exception时会去询问它的supervisor如何去处理(恢复,重启,停止)。

    4.通过gracefulStop 方法stop actors,适用于设置等待终止时间和通过stop若干个actor的场景

    实践

    import akka.actor.AbstractActor;
    import akka.actor.Props;
    import akka.event.Logging;
    import akka.event.LoggingAdapter;
    import java.util.HashMap;
    import java.util.Map;
    public class RequestActor5 extends AbstractActor {
        protected final String name;
        protected final LoggingAdapter log = Logging.getLogger(context().system(),this);
        protected final Map<String, Object> map = new HashMap<>();
        public RequestActor5(String name) {
            this.name = name;
        }
        static Props props(String name) {
            return Props.create(RequestActor5.class, name);
        }
        @Override
        public Receive createReceive() {
            return receiveBuilder()
                    .matchEquals("done",message -> {
                        getContext().stop(getSelf());
                    })
                    .match(String.class,message->{
                        log.info("Received Request {}",message);
                        map.put("StringMessage",message);
                    })
                    .matchAny(o->log.info("Received unknow message {}",o))
                    .build();
        }
        @Override
        public void postStop() throws Exception {
            System.out.println("RequestActor5 is done");
        }
    }
    
    
    import akka.actor.ActorRef;
    import akka.actor.ActorSystem;
    import akka.actor.Kill;
    import akka.actor.PoisonPill;
    import akka.testkit.TestActorRef;
    import org.junit.jupiter.api.Test;
    class RequestActor5Test {
        ActorSystem system = ActorSystem.create();
        @Test
        public void test1() {
            TestActorRef<RequestActor5> actorRef = TestActorRef.create(system, RequestActor5.props("request"));
            actorRef.tell(Kill.getInstance(), ActorRef.noSender());
        }
        @Test
        public void test2() {
            TestActorRef<RequestActor5> actorRef = TestActorRef.create(system, RequestActor5.props("request"));
            actorRef.tell(PoisonPill.getInstance(), ActorRef.noSender());
        }
        @Test
        public void test3() {
            TestActorRef<RequestActor5> actorRef = TestActorRef.create(system, RequestActor5.props("request"));
            actorRef.tell("done", ActorRef.noSender());
        }
        @Test
        public void test4() {
            TestActorRef<RequestActor5> actorRef = TestActorRef.create(system, RequestActor5.props("request"));
            actorRef.tell("message", ActorRef.noSender());
            system.stop(actorRef);
        }
    }
    
    

  • 相关阅读:
    HTTP报文详解
    常用的HTTP协议
    URL详解
    log4net工作原理(2)
    《Linux内核设计与实现》读书笔记(十七)- 设备与模块
    《Linux内核设计与实现》读书笔记(十六)- 页高速缓存和页回写
    《Linux内核设计与实现》读书笔记(十五)- 进程地址空间(kernel 2.6.32.60)
    《Linux内核设计与实现》读书笔记(十四)- 块I/O层
    随手记代码
    记录一下WPF中自寄宿asp.net服务添加urlacl的问题
  • 原文地址:https://www.cnblogs.com/jj81/p/13970333.html
Copyright © 2020-2023  润新知