Reactive Streams 规范接口组成

API组成部分

响应式流 JVM 规范由下列Reactive Streams接口组成:

  • Publisher
  • Subscriber
  • Subscription
  • Processor

Publisher 发布者会提供(可能)是无限多个元素,并按照 Subscriber 订阅者的处理速度进行发布(需求驱动)。

当调用 Publisher.subscribe(Subscriber) 后,有可能的 Subscriber 方法调用顺序为

 onSubscribe onNext* (onError | onComplete)?

这代表 onSubscribe 始终会被调用,接下来是 0-N个 onNext 的事件;

当 onNext 调用结束后如果有错误会发送 onError 信号,若一切正常会发送 onComplete 通知下游没有更多元素了;

如果中途 Subscription 订阅被取消,那么可能 onError 和 onComplete 都不会被调用。
 

Publisher发布者

public interface Publisher<T> { 
    public void subscribe(Subscriber<? super T> s);
}
  1. Publisher发送给Subscriber的onNext信号总次数必须小于或等于Subscriber在当前Subscription中所请求的元素的个数。
    这条规则确保Publisher不会发送多于Subscriber请求的元素个数,这样隐性地表达了一个happens-before的关系,
    即请求元素发生在接收到元素之前。
  2. Publisher可以发送少于Subscriber请求的元素,并且通过发送onComplete或onError信号终止当前的Subscription。
    这条规则声明Publisher并不能保证可以提供Subscriber所请求的元素个数,且原因可以是多样的(没有那么多元素,获取元素失败等等)。
  3. onSubscribe,onNext,onError和onComplete信号必须按照顺序进行发送。
    这样确保在多线程的情况下能够确保信号之间的happens-before关系。
  4. 如果Publisher报错,那么它必须发送onError信号给Subscriber。
  5. 如果Publisher正常结束,那么它必须发送onComplete信号给Subscriber。
  6. 当Publisher向Subscriber发送了onError或onComplete信号后,当前Subscriber上的Subscription必须被视为已取消。
  7. 当订阅到达终结状态时(已发送onError或onComplete信号),Publisher不得再发布其他更多信号。
  8. 如果当前订阅Subscription已经被取消,那么相关的Subscriber最终必须停止被发送信号。
    换句话说,当Subscription.cancel()被调用后,Subscriber仍有可能接收到一些元素,因为取消调用可能是异步发生的。
  9. Publisher.subscribe方法中必须先于其他方法调用Subscriber上的onSubscribe方法,并且必须正常返回(除了Subscriber为null值的情况)。
    其他所有的异常情况都需要在onSubscribe调用结束后通过onError方法调用来通知订阅者。
  10. Publisher.subscribe方法可以被多次调用但每次都必须是一个不同的Subscriber。也就是相关的Publisher和Subscriber不能被关联多于一次。
  11. Publisher可以支持多个Subscriber并且自由决定当前的Subscription是单播unicast还是组播multicast。

Subscriber订阅者

public interface Subscriber<T> {
    public void onSubscribe(Subscription s);
    public void onNext(T t);
    public void onError(Throwable t);
    public void onComplete();
}
  1. Subscriber必须通过调用Subscription.request(long n)来传达自己的需求,这样确保由Subscriber来决定何时接收处理多少个onNext发送过来的元素。
  2. 如果Subscriber怀疑它对信号的处理会影响到Publisher的响应时,它应该确保发送信号的过程是异步的。
    也就是说从线程执行的角度来讲,Subscriber的信号处理不应该影响Publisher的程序进度。
  3. Subscriber.onComplete()和Subscriber.onError(Throwable t)方法中不应该调用Subscription或Publisher上的任何方法,这样确保在处理终态信号时不会有竞态条件产生。
  4. 当Subscriber接收到onComplete或者onError(Throwable t)的调用后,它必须视当前的Subscription为已取消。
  5. 当Subscriber已经有了一个活跃的Subscription之后,跟其他Publisher之间的Subscription(在接收到onSubscribe信号后)必须通过调用Subscription.cancel()来取消。
    因为在任何时候,一个Subscriber只能跟至多一个Publisher进行交互,多余的订阅必须被取消。
  6. 当Subscriber不再需要某个订阅时,必须调用该订阅上的cancel方法。
  7. Subscriber必须确保对Subscription上request(long n)和cancel()方法的调用是依次分开进行的,不能有时间上的重合(常见于多线程并发,需要用锁来确保资源独占)。
  8. Subscriber在调用了Subscription.cancel()之后仍要做好接收多个onNext信号的准备,因为仍有可能存在待处理的元素。
    取消订阅操作不会保证立即执行清理操作。
  9. 即使前序没有Subscription.request(long n)的调用,Subscriber仍然要做好接收onComplete信号的准备。
  10. 即使前序没有Subscription.request(long n)的调用,Subscriber仍然要做好接收onError信号的准备,
    因为Publisher的出错可能跟需求发送毫不相关。
  11. Subscriber必须确保所有的信号发送方法的调用发生在该信号对应的处理之前,
    也就是Subscriber的实现需要保证异步处理时的线程安全。
  12. 对给定的Subscriber来讲,Subscriber.onSubscribe方法最多被调用一次。
  13. 与Publisher的第9条规则类似,调用Subscriber的onSubscribe,onNext, onError或onComplete方法必须正常返回(除非元素为null值);
    如果Subscriber需要向Publisher表明自身的失败状态,必须通过取消订阅的操作来进行

Subscription订阅

public interface Subscription {
    public void request(long n);
    public void cancel();
}
  1. Subscription.request和Subscription.cancel必须在对应Subscriber的上下文中被调用。
    这样是为了确保Subscription描述的是Subscriber和Publisher之间的唯一关联关系
  2. Subscription必须允许Subscriber在onNext或者onSubscribe中同步调用Subscription.request。
    因为onNext可能是在request的栈帧上被调用,实际上也就是表明request必须是可重入的。
  3. Subscription.request必须为可能出现的Publisher和Subscriber间的同步递归调用设置上限,
    以免出现栈溢出。
  4. Subscription.request应该即时返回,以免影响其调用者的响应。也就是说request线程上不应该执行复杂计算。
  5. Subscription.cancel应该即时返回,以免影响其调用者的响应,并且它也必须是线程安全和幂等的。
  6. 当Subscription被取消之后,任何额外的Subscription.request(long n)方法都应该是空操作。
  7. 当Subscription被取消之后,任何额外的Subscription.cancel()方法都应该是空操作。
  8. 当Subscription没有被取消时,Subscription.request(long n)必须指明subscriber在下一批请求中会注册多少个元素。
  9. 当Subscription没有被取消时,如果Subscription.request(long n)的入参n<0,那么必须调用onError来指定java.lang.IllegalArgumentException异常。
  10. 当Subscription没有被取消时,Subscription.request(long n)可以同步调用当前或其他Subscriber(s)的onNext方法。
  11. 当Subscription没有被取消时,Subscription.request(long n)可以同步调用当前或其他Subscriber(s)的onComplete或onError方法。
  12. 当Subscription没有被取消时,Subscription.cancel()必须要求Publisher最终停止发送元素给Subscriber。
  13. 当Subscription没有被取消时,Subscription.cancel()必须要求Publisher最终删除任何对当前Subscriber的对象引用。
  14. 当Subscription没有被取消时,调用Subscription.cancel()后可能会导致Publisher进入shut-down状态(如果它没有参与任何活跃的Subscription的话)。
  15. 调用Subscription.cancel()必须正常返回。
  16. 调用Subscription.request(long n)必须正常返回。
  17. 一个Subscription必须支持无限次调用request并且必须支持声明2^63-1(java.lang.Long.MAX_VALUE)个元素的需求。
  18. 如果请求的元素大于2^63-1,那么Publisher可以将它当作无穷多来处理(不再关注当前订阅的需求状态)。

Processor处理器

public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {
}

Processor代表一个处理中的状态,同时是一个Subscriber和Publisher,并且必须同时遵循二者的规范。

Processor可以尝试从onError信号中恢复状态。如果它这么做了,那么它必须将当前Subscription视为已取消,
否则它必须将onError信号传达给它的Subscribers。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔道不误砍柴功

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值