问题描述
基本上我想要的演员,使得使用两个定时器和存储功能。
在 Scala 中,我们可以执行以下操作 - extends AbstractActor with Timer with Stash
在 Java 中,我发现了两个类 - AbstractActorWithTimers
和AbstractActorWithStash
。
不幸的是,我无法在 Java 中扩展这两个类。
有什么推荐的方法在 Java 中这样做吗?
1楼
甚至我也陷入了同样的问题。 我想创建一个状态机,我需要同时使用 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)); } } }
2楼
最近我偶然发现了这个问题,我们通过在 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.
}
}