从响应流SubmissionPublisher接收项目

时间:2017-03-14 18:56:11

标签: reactive-programming java-9 reactive-streams

我正在尝试Java 9中的一些新功能。所以我组织了一个测试,让一个发布者以给定的速率发出数字。我还实现了一个订阅者来收听这些出版物,然后将它们打印到控制台。

虽然我可能不完全了解如何使用此Api,因为onNext()方法不打印任何内容而getLastItem()仅返回0.

似乎有效的唯一部分是正确初始化onSubscribe()变量的lastItem

@Test
public void testReactiveStreams(){
    //Create Publisher
    SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>();

    //Register Subscriber
    TestIntegerSubscriber subscriber = new TestIntegerSubscriber();
    publisher.subscribe(subscriber);

    assertTrue(publisher.hasSubscribers());

    //Publish items
    System.out.println("Publishing Items...");

    List.of(1,2,3,4,5).stream().forEach(i -> {
        publisher.submit(i);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // blah
        }
    });
    assertEquals(5, subscriber.getLastItem());

    publisher.close();
}


private class TestIntegerSubscriber implements Flow.Subscriber<Integer> {

    private int lastItem;
    @Override
    public void onSubscribe(Flow.Subscription subscription) {
        System.out.println("Subscribed");
        lastItem = 0;
    }

    @Override
    public void onNext(Integer item) {
        System.out.println("Received : "+item);
        lastItem += 1; // expect increment by 1
        assertTrue(lastItem == item);
    }

    @Override
    public void onError(Throwable throwable) {
        // nothing for the moment
    }

    @Override
    public void onComplete() {
        System.out.println("Completed");
    }

    public int getLastItem(){
        return lastItem;
    }
}

有人可以告诉我,我的测试中出错了吗?我希望测试打印这些数字并返回5作为最后一项。

我不得不说我只使用Angular2中的Observables和Subjects,虽然它们似乎更容易理解。

2 个答案:

答案 0 :(得分:4)

Flow API实现了一项名为 backpressure explained here in the context of RxJava)的功能,这意味着发布商不应该通过发布项目而不是处理它们来淹没订阅者。 JDK 9实现的方式是让订阅者从订阅中请求项目。

对于您的测试,TestIntegerSubscriber应该请求项onSubscription,让我们说10,并跟踪onNext被调用的频率,以便它可以请求更多一旦推了10个项目。

我写了a section about the Flow API更详细的内容。它还描述了发布者,订阅者和订阅之间的交互:

  1. 创建PublisherSubscriber
  2. 使用Publisher::subscribe订阅订阅者。
  3. 发布商创建Subscription并使用它调用Subscriber::onSubscription,以便订阅者可以存储订阅。
  4. 在某些时候订阅者调用Subscription::request来请求多个项目。
  5. 发布商通过致电Subscriber::onNext开始将物品交给订阅者。它永远不会发布超过所请求数量的项目。
  6. 发布商可能会在某些时候耗尽或遇到麻烦,并分别致电Subscriber::onCompleteSubscriber::onError
  7. 订阅者可能会不时继续请求更多项目,或通过致电Subscription::cancel来切断连接。

答案 1 :(得分:0)

我已经做了一些更多的研究,我可以看到代码可以通过在Subscription实现中添加Subscriber成员来实现,如下所示:

public class MySubscriber<T> implements Subscriber<T> {  
  private Subscription subscription;  

...

@Override
        public void onSubscribe(Flow.Subscription subscription) {
            this.subscription = subscription;
            System.out.println("Subscribed");
            subscription.request(1);
            lastItem = 0;
        }

...

  @Override
        public void onNext(Integer item) {
            System.out.println("Received : "+item);
            lastItem += 1; // expect increment by 1
            assertTrue(lastItem == item);
            subscription.request(1);
        }

其中subscription.request(1);我认为这意味着我正在使用发布商的1件商品。我不知道......如果有人向我澄清,那实际上会很好。