Java Akka调度程序:仅在当前运行完成时运行下一步

Java Akka调度程序:仅在当前运行完成时运行下一步,java,akka,Java,Akka,使用Akka Scheduler调度作业的方式如下(至少从文档中可以看到): 但是,我不明白如何确保只有在当前运行完成时才能进行下一次运行。我一直在四处寻找,但没有成功:(调度程序意味着你需要周期性的东西,现在如果你的第二次运行取决于你的第一次运行,那么你为什么还要创建一个调度程序呢 只需创建两个参与者,一个经理参与者和另一个子参与者 当任务是成功时,子参与者向父参与者发送一条成功消息,因此父参与者要求子参与者再次运行任务。这保证了任务以周期性顺序运行,并且在前一个任务成功时也会运行 因此,基本

使用Akka Scheduler调度作业的方式如下(至少从文档中可以看到):


但是,我不明白如何确保只有在当前运行完成时才能进行下一次运行。我一直在四处寻找,但没有成功:(

调度程序意味着你需要周期性的东西,现在如果你的
第二次运行取决于你的
第一次运行,那么你为什么还要创建一个调度程序呢

只需创建两个参与者,
一个经理参与者
和另一个
子参与者

当任务是
成功
时,
子参与者
父参与者
发送一条成功消息,因此父参与者要求
子参与者
再次运行任务。这保证了任务以周期性顺序运行,并且在前一个任务成功时也会运行

因此,基本上,您必须在
参与者的receive方法中实现相应的匹配case类


希望这有帮助!

调度程序意味着您需要周期性地执行某些操作,现在如果您的
第二次运行取决于您的
第一次运行,那么您为什么还要创建调度程序呢

system.scheduler().schedule(
    Duration.Zero(),
    Duration.create(5, TimeUnit.SECONDS),
    workerActor,
    new MessageToTheActor(),
    system.dispatcher(), ActorRef.noSender());
只需创建两个参与者,
一个经理参与者
和另一个
子参与者

当任务是
成功
时,
子参与者
父参与者
发送一条成功消息,因此父参与者要求
子参与者
再次运行任务。这保证了任务以周期性顺序运行,并且在前一个任务成功时也会运行

因此,基本上,您必须在
参与者的receive方法中实现相应的匹配case类

希望这有帮助

system.scheduler().schedule(
    Duration.Zero(),
    Duration.create(5, TimeUnit.SECONDS),
    workerActor,
    new MessageToTheActor(),
    system.dispatcher(), ActorRef.noSender());
上述代码表示每5秒,调度程序将向参与者
workerActor
发送
消息

正如您所知,actor默认只包含一个线程(除非您配置了实例>1的nr),这意味着发送到
workActor
的所有消息都将缓冲在
邮箱中,因为只有一个线程可以调用
actor
receive
函数

换句话说,您总是可以确保下一次运行只在当前运行完成时发生,因为默认情况下,只有一个线程同时为参与者工作

上述代码表示每5秒,调度程序将向参与者
workerActor
发送
消息

正如您所知,actor默认只包含一个线程(除非您配置了实例>1的nr),这意味着发送到
workActor
的所有消息都将缓冲在
邮箱中,因为只有一个线程可以调用
actor
receive
函数


换句话说,您总是可以确保只有在当前运行完成时才进行下一次运行,因为默认情况下,只有一个线程同时为参与者工作。

调度程序对于您的用例来说是错误的工具

另一种选择是Akka Stream(下面的代码改编自链接文档中的示例,并借用其中定义的实用程序类)。您需要调整worker actor以处理一些与流状态相关的消息,并使用确认消息进行回复。确认消息用作背压信号,并指示actor已准备好处理下一条
消息到actor
消息。worker actor将看起来有些问题例如:

enum Ack {
  INSTANCE;
}

static class StreamInitialized {}
static class StreamCompleted {}
static class StreamFailure {
  private final Throwable cause;
  public StreamFailure(Throwable cause) { this.cause = cause; }

  public Throwable getCause() { return cause; }
}

public class MyWorker extends AbstractLoggingActor {
  @Override
  public Receive createReceive() {
    return receiveBuilder()
      .match(StreamInitialized.class, init -> {
        log().info("Stream initialized");
        sender().tell(Ack.INSTANCE, self());
      })
      .match(MessageToTheActor.class, msg -> {
        log().info("Received message: {}", msg);
        // do something with the message...
        sender().tell(Ack.INSTANCE, self());
      })
      .match(StreamCompleted.class, completed -> {
        log().info("Stream completed");
      })
      .match(StreamFailure.class, failed -> {
        log().error(failed.getCause(),"Stream failed!");
      })
      .build();
  }
}
要对上述参与者使用
Sink.actorRefWithAck

final ActorSystem system = ActorSystem.create("MySystem");
final Materializer materializer = ActorMaterializer.create(system);

ActorRef workerActor = system.actorOf(Props.create(MyWorker.class, "worker"));

Source<MessageToTheActor, NotUsed> messages = Source.repeat(new MessageToTheActor());

Sink<String, NotUsed> sink = Sink.<String>actorRefWithAck(
  workerActor,
  new StreamInitialized(),
  Ack.INSTANCE,
  new StreamCompleted(),
  ex -> new StreamFailure(ex)
);

messages.runWith(sink, materializer);

调度程序对于您的用例来说是错误的工具

另一种选择是Akka Stream(下面的代码改编自链接文档中的示例,并借用其中定义的实用程序类)。您需要调整worker actor以处理一些与流状态相关的消息,并使用确认消息进行回复。确认消息用作背压信号,并指示actor已准备好处理下一条
消息到actor
消息。worker actor将看起来有些问题例如:

enum Ack {
  INSTANCE;
}

static class StreamInitialized {}
static class StreamCompleted {}
static class StreamFailure {
  private final Throwable cause;
  public StreamFailure(Throwable cause) { this.cause = cause; }

  public Throwable getCause() { return cause; }
}

public class MyWorker extends AbstractLoggingActor {
  @Override
  public Receive createReceive() {
    return receiveBuilder()
      .match(StreamInitialized.class, init -> {
        log().info("Stream initialized");
        sender().tell(Ack.INSTANCE, self());
      })
      .match(MessageToTheActor.class, msg -> {
        log().info("Received message: {}", msg);
        // do something with the message...
        sender().tell(Ack.INSTANCE, self());
      })
      .match(StreamCompleted.class, completed -> {
        log().info("Stream completed");
      })
      .match(StreamFailure.class, failed -> {
        log().error(failed.getCause(),"Stream failed!");
      })
      .build();
  }
}
要对上述参与者使用
Sink.actorRefWithAck

final ActorSystem system = ActorSystem.create("MySystem");
final Materializer materializer = ActorMaterializer.create(system);

ActorRef workerActor = system.actorOf(Props.create(MyWorker.class, "worker"));

Source<MessageToTheActor, NotUsed> messages = Source.repeat(new MessageToTheActor());

Sink<String, NotUsed> sink = Sink.<String>actorRefWithAck(
  workerActor,
  new StreamInitialized(),
  Ack.INSTANCE,
  new StreamCompleted(),
  ex -> new StreamFailure(ex)
);

messages.runWith(sink, materializer);

Scheduler意味着你需要周期性的东西,现在如果你的第二次运行依赖于你的第一次运行,那么你为什么还要创建一个Scheduler。只需创建两个参与者,一个管理者参与者和另一个子参与者。当任务成功时,子参与者向父参与者发送一条成功消息,然后父参与者询问子参与者参与者,然后第二次运行任务。这可以保证任务按周期顺序运行,并且在上一次任务成功时也可以。希望这有帮助!确实非常有用。如果可能,将其添加为答案,以便我可以接受。当然,让我将其添加为答案。看一看,我已经更新了帖子。调度程序意味着您需要一些内容以周期性的方式,如果第二次运行依赖于第一次运行,那么为什么还要创建计划程序。只需创建两个参与者,一个管理者参与者,另一个子参与者。当任务成功时,子参与者向父参与者发送一条成功消息,然后父参与者要求子参与者再次运行任务。这保证了任务是按周期顺序运行的,并且在前一个任务成功时也是如此。希望这有帮助!确实非常有用。如果可能,将其添加为答案,以便我可以接受。当然,让我将其添加为答案。看一看,我已经更新了帖子。这看起来很棒@Jeffrey。我假设
源代码。重复
重复工作人员角色完成后立即呼叫。如果是这种情况,那么我如何确保在工作人员角色完成和开始处理下一个请求之间有一个暂停(比方说5秒)?这看起来很棒@Jeffrey。我假设