当前位置: 代码迷 >> java >> Akka Java API - 如何扩展 AbstractActor 并同时使用 Timers 和 Stash 函数
  详细解决方案

Akka Java API - 如何扩展 AbstractActor 并同时使用 Timers 和 Stash 函数

热度:53   发布时间:2023-07-25 20:05:00.0

基本上我想要的演员,使得使用两个定时器存储功能。

在 Scala 中,我们可以执行以下操作 - extends AbstractActor with Timer with Stash

在 Java 中,我发现了两个类 - AbstractActorWithTimersAbstractActorWithStash

不幸的是,我无法在 Java 中扩展这两个类。

有什么推荐的方法在 Java 中这样做吗?

甚至我也陷入了同样的问题。 我想创建一个状态机,我需要同时使用 stash 和 timer。

所以在这种情况下,我有两个选择:-

  • 使用 AbstractFSMWithStash:- 我不喜欢这个,因为我不确定它是否是我的解决方案中的 scalabel

  • 使用 Typed Actors,您可以在其中实际组合计时器和存储,请参考下面的测试用例代码:-

     import akka.actor.testkit.typed.javadsl.TestKitJunitResource; import akka.actor.typed.ActorRef; import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.Behaviors; import akka.actor.typed.javadsl.StashBuffer; import akka.actor.typed.javadsl.TimerScheduler; import org.junit.ClassRule; import org.junit.Test; import org.scalatest.junit.JUnitSuite; import java.time.Duration; public class CountingActor extends JUnitSuite { public static final class DeviceMessage implements Msg{ private int id; public DeviceMessage(int id) { this.id = id; } public int getId() { return id; } } interface Msg{} private static final class TimeOut implements Msg{} private static final Object TIMER_KEY = new Object(); private static final StashBuffer<Msg> buffer = StashBuffer.create(10000); public static Behavior<Msg> behavior(Duration after) { return Behaviors.withTimers(timers -> active(timers, after)); } private static Behavior<Msg> idle(TimerScheduler<Msg> timers, Duration after) { return Behaviors.receive(Msg.class) .onMessage(DeviceMessage.class, (ctx, msg) -> { System.out.println("in idle state got message:"+msg.getId()); buffer.stash(msg); return Behaviors.same(); }) .onMessage(TimeOut.class,(ctx,msg)->{ System.out.println("in idle state got TimeOut"); timers.cancel(TIMER_KEY); return buffer.unstashAll(ctx,active(timers,after)); }) .build(); } private static Behavior<Msg> active(TimerScheduler<Msg> timers, Duration after) { return Behaviors.receive(Msg.class) .onMessage(DeviceMessage.class, (ctx, msg) -> { System.out.println("got message:"+msg.getId()); timers.startSingleTimer(TIMER_KEY, new TimeOut(), after); System.out.println(" going to idle state " ); return idle(timers,after); }) .build(); } @ClassRule public static final TestKitJunitResource testKit = new TestKitJunitResource(); @Test public void stashingExample() throws Exception { ActorRef<Msg> ref= testKit.spawn(CountingActor.behavior(Duration.ofSeconds(2))); for(int i=0;;i++){ ref.tell(new DeviceMessage(i)); } } }

最近我偶然发现了这个问题,我们通过在 Scala 项目中创建一个抽象类然后在 Java 中扩展它来规避它。

这个scala项目其实就是我们maven-multi-module项目中使用akka(经典)的一个模块。 该项目包含这个没有主体的抽象类:

import akka.actor.{AbstractActor, Stash, Timers}

/**
  * An abstract actor that has both stash and timers.
  */
abstract class AbstractActorWithStashAndTimers extends AbstractActor with Stash with Timers {
}

一旦您将 scala 项目编译成 jar,并将该 jar 放在您的 Java 项目类路径中,您就可以像 akka 中的任何其他抽象 actor 类一样在 Java 中使用它:

public class MyConcreteActor extends AbstractActorWithStashAndTimers {
    @Override
    public final Receive createReceive() {
         // you can use stash() and timers() here.
    }
}
  相关解决方案