Java 即使在条件失败后,Akka在处理下一个元素时也会流取数据

Java 即使在条件失败后,Akka在处理下一个元素时也会流取数据,java,scala,akka,akka-stream,Java,Scala,Akka,Akka Stream,我有一个非常简单的演员,只需打印号码:- public class PrintLineActor extends AbstractLoggingActor { @Override public Receive createReceive() { return receiveBuilder() .match(Integer.class, i -> { System.out.println("Processing: "

我有一个非常简单的演员,只需打印号码:-

public class PrintLineActor extends AbstractLoggingActor {

  @Override
  public Receive createReceive() {
    return receiveBuilder()
        .match(Integer.class, i -> {
          System.out.println("Processing: " + i);
          sender().tell(i, self());
        }).build();
  }
}
现在,我有一个流来打印偶数,直到遇到奇数元素:-

  @Test
  public void streamsTest() throws Exception {

    ActorSystem system = ActorSystem.create("testSystem");
    ActorRef printActor = system.actorOf(Props.create(PrintLineActor.class));

    Integer[] intArray = new Integer[]{2,4,6,8,9,10,12};
    CompletionStage<List<Integer>> result = Source.from(Arrays.asList(intArray))
        .ask(1, printActor, Integer.class, Timeout.apply(10, TimeUnit.SECONDS))
        .takeWhile(i -> i != 9)
        .runWith(Sink.seq(), ActorMaterializer.create(system));

    List<Integer> result1 = result.toCompletableFuture().get();
    System.out.println("Result :- ");
    result1.forEach(System.out::println);
  }
为什么10由演员处理?如何阻止这一切

编辑:

我试着通过记录事件的时间戳进行调试,只是想看看是否在9实际完成之前处理了10,但没有,10是在9完全处理之后处理的。以下是日志:-

Before Ask: 2 in 1596035906509
Processing inside Actor: 2 at 1596035906509
Inside TakeWhile 2 at  in 1596035906509

Before Ask: 4 in 1596035906609
Processing inside Actor: 4 at 1596035906610
Inside TakeWhile 4 at  in 1596035906610

Before Ask: 6 in 1596035906712
Processing inside Actor: 6 at 1596035906712
Inside TakeWhile 6 at  in 1596035906712

Before Ask: 8 in 1596035906814
Processing inside Actor: 8 at 1596035906814
Inside TakeWhile 8 at  in 1596035906815

Before Ask: 9 in 1596035906915
Processing inside Actor: 9 at 1596035906915
Inside TakeWhile 9 at  in 1596035906916

Before Ask: 10 in 1596035907017 //so 10 is taken much after the 9 is processed fully
Processing inside Actor: 10 at 1596035907017

Result :- 
2
4
6
8

另外,如果我用direct.map(print..)替换.ask,那么10不会被打印出来。所以当涉及actor.ask时,为什么会发生这种情况对我来说很奇怪。

因为您是异步地询问而不是同步地打印actor。在您的跑步中:

  • 消息9到达PrintActor,打印“处理:9”
  • 消息10到达PrintActor,打印“处理:10”
  • 您的Akka流从PrintActor接收消息9的响应消息,完成Akka流,因此结果中既没有9也没有10

要解决确切的问题,请删除异步ask,改为同步打印。但不确定PrintActor是否只是一个类比,让我知道。

akka流正在通过不同的流缓冲值。请注意,10是进位的,但它不是结果的一部分。如果愿意,可以配置缓冲区大小:

.ask(1, printActor, Integer.class, Timeout.apply(10, TimeUnit.SECONDS)).buffer(1, OverflowStrategy.backpressure)

不,这不是事件的顺序。此流是连续的,没有并行性。我用一些调试日志编辑了这个问题,以指示事件的顺序。演员被要求在9成功处理后处理10。我不是说,9比10晚处理。我是说在PrintActor处理10之后,您的Akka流从消息9接收ask响应,并在从消息10接收ask响应之前完成流。这就是为什么。不,来自消息9的ask响应远早于10发送给actor。您可以在调试日志中看到这一点。请更新有关打印日志位置的代码。Y,我放置了一个映射(x->{print(“询问前:”+x);返回x;)在.ask之前,我也在takeWhile中打印了时间戳。看起来mapAsync/ask在发出元素时会从上游提取元素。因此,正如你所说,没有隐含的方法可以做到这一点:(感谢你的回答。这不起作用-10仍然由actor处理。我尝试放入.buffer(1,…)在问之前,问之后,演员不知何故仍然得到10分,我不希望10分被处理,因为你无法控制akka流停止的方式。这是你能做的最好的事情。为了更好地理解这一点,你可以在水槽中打印结果,加上时间戳,看看之前发生了什么。重复几次。我很高兴确保在拒绝9之前至少处理一次10。我还在takeWhile()中添加了100ms的延迟。因此,在takeWhile()之后的100ms延迟之后,10将从源代码中删除
.ask(1, printActor, Integer.class, Timeout.apply(10, TimeUnit.SECONDS)).buffer(1, OverflowStrategy.backpressure)