Reactor GroupedFlux - 等待完成

时间:2018-02-02 13:27:46

标签: project-reactor

有一个异步发布者,如同下面的那个,是否有一种方法可以让Project Reactor等到整个流完成处理?
当然,无需在未知时间内添加睡眠......

@Test
public void groupByPublishOn() throws InterruptedException {
    UnicastProcessor<Integer> processor = UnicastProcessor.create();

    List<Integer> results = new ArrayList<>();
    Flux<Flux<Integer>> groupPublisher = processor.publish(1)
                                                  .autoConnect()
                                                  .groupBy(i -> i % 2)
                                                  .map(group -> group.publishOn(Schedulers.parallel()));

    groupPublisher.log()
                  .subscribe(g -> g.log()
                                   .subscribe(results::add));

    List<Integer> input = Arrays.asList(1, 3, 5, 2, 4, 6, 11, 12, 13);
    input.forEach(processor::onNext);
    processor.onComplete();

    Thread.sleep(500);

    Assert.assertTrue(results.size() == input.size());
}

2 个答案:

答案 0 :(得分:4)

您可以替换这些行:

 groupPublisher.log()
                  .subscribe(g -> g.log()
                                   .subscribe(results::add));

用这个

groupPublisher.log()
              .flatMap(g -> g.log()
                             .doOnNext(results::add)
              )
              .blockLast();

flatMap是一个比subscribe-subscri-subscribe更好的模式,它将负责为您订阅该组。

doOnNext负责消费副作用(为集合添加值),使您无需在订阅中执行该操作。

blockLast()取代订阅,而不是让你为它阻塞的事件提供处理程序直到完成(并返回最后一个发出的项目,但你已经在doOnNext中处理了这个)。

答案 1 :(得分:0)

使用 blockLast()的主要问题是,如果您的操作无法完成,您将永远不会释放您的管道。

您需要做的是获取 Disposable 并检查是否已完成管道,这意味着布尔 isDisposed 它将返回true。

然后由您决定是否要暂停,例如延迟计数实现:)

int count = 0;

@Test
public void checkIfItDisposable() throws InterruptedException {
    Disposable subscribe = Flux.just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
            .map(number -> {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return number;
            }).subscribeOn(Schedulers.newElastic("1"))
            .subscribe();

    while (!subscribe.isDisposed() && count < 100) {
        Thread.sleep(400);
        count++;
        System.out.println("Waiting......");
    }
    System.out.println("It disposable:" + subscribe.isDisposed());

如果您想使用 blockLast ,至少要添加超时

@Test
public void checkIfItDisposableBlocking() throws InterruptedException {
    Flux.just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
            .map(number -> {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return number;
            }).subscribeOn(Schedulers.newElastic("1"))
            .blockLast(Duration.of(60, ChronoUnit.SECONDS));
    System.out.println("It disposable");
}

如果您需要更多ide https://github.com/politrons/reactive

,可以在此处查看更多Reactor示例