正如标题所说的,这篇帖子主要说下,在解决这个问题的时候所遇到的问题
先说下背景:
1,一个请求,启动多个actor去执行任务,当任务执行过程中,又请求的一次,进行了重复请求
这种情况下,会出现异常InvalidActorNameException,也就是说actor的名字重复了
首先想到将正在执行的actor关闭,actor的关闭我这里说一种,actorSysm.stop(actor);
actorSystem类型是ActorSystem,如果不知道这个是怎么来的,去搜索下怎么创建actor,自然就有了
但是这里有个问题,stop的命令不会立即终止actor,不像linux的kill一样,直接杀死,而是要发送让其
死亡的消息,但是我们不可能等到这个actor彻底死了,才去创建新的actor
这期间试了几种方法,都不能满足需求
最后,只能曲线救国
那就是每次请求进来,重新建立actorSystem
ActorSystem systemo = system.apply("AkkaVehicleReport");
然后将之前的actorSystem关闭
system.shutdown();
最后将之前的actorSystem的引用指向新建的actorSystem
system = systemo;
这样做的效果就是每次都是新的actorSystem去创建actor执行任务,不会出现名字重复的问题
同时关闭了之前的actorSystem,之前创建的actor会逐层被杀死,解决了不会因为重复提交而造成
一直创建actor的问题,
因为我的actor执行的完成之后会将数据保存到一个地方,这么操作还有一个意外收获
那就是之前的actor未被杀死之前执行完的数据会被保存下来,新建的actor不需要再次执行
提高了数据利用率
下面把相对完整的代码贴出来,欢迎大家指导
注入部分:
@Autowired
private ActorSystem system;
这里说下,如果你无法注入这个actorSystem,需要增加一部分代码,这里不做解释,可以自己搜下,找不到可以找我-469798404
方法内部:
ActorSystem systemo = system.apply("AkkaVehicleReport");
system.shutdown();
system = systemo;
for (int i = 1; i <= 20; i++) { ReportMessage msg = new ReportMessage(); String actorName = session.getId() + "pageActor" + i; try { actorList.add(actorName); ActorRef pageActor = system.actorOf(SpringExtProvider.get(system).props(PageActor.class), actorName); System.out.println("---" + actorName + "-----------create"); pageActor.tell(msg, ActorRef.noSender()); } catch (InvalidActorNameException e) { e.printStackTrace(); } }
创建了20个actor,去执行任务
@Override public void onReceive(Object msg) throws Exception { if(msg instanceof ReportMessage){ //查询数据,处理数据 ReportMessage remsg = (ReportMessage)msg; //判断该部分数据是否处理完成 if(//处理完成){ System.out.println("----------重复---done---" + this.self().path().name()); }else{//未处理完成 //重新处理 System.out.println("-------------done---" + this.self().path().name()); } getContext().stop(this.getSelf()); } else{ unhandled(msg); } }
整体的结构就是这样,删掉了一些业务代码
整体思路就是这样
重复提交时,创建actor的动作和停止正在执行的actor的动作时同时操作的,这样又可以节省一部分时间
只是可能要多消耗一些性能