首先出现响应式编程理念,然后出现响应式编程实现,再然后出现响应式规范,响应流主要解决处理元素流的问题—如何将元素流从发布者传递到订阅者,不而不需要发布者阻塞,或者要求订阅者有无限的缓冲区,有限的缓冲区在到达缓冲上界的时候,对到达的元素进行丢弃或者拒绝,订阅者可以异步通知发布者降低或提升数据生产发布的速率,它是响应式编程实现效果的核心特点。
而响应式规范则是一种倡议,遵循此倡议的系统可以让数据在各个响应式系统中都实现响应式的处理数据,规范在Java中的形式就是接口,也就是我们本篇的主题Flow 类,对于一项标准而言,它的目的自然是用更少的协议来描述交互。
响应式流从2013年开始,作为提供非阻塞背压的异步流处理标准的倡议。 它旨在解决处理元素流的问题——如何将元素流从发布者传递到订阅者,而不需要发布者阻塞,或订阅者有无限制的缓冲区或丢弃。
响应式流模型非常简单——订阅者向发布者发送多个元素的异步请求。 发布者向订阅者异步发送多个或稍少的元素。
在2015年,出版了用于处理响应式流的规范和Java API。 有关响应式流的更多信息,请访问http://www.reactive-streams.org/。 Java API 的响应式流只包含四个接口:
- Publisher<T>
- Subscriber<T>
- Subscription
- Processor<T,R>
发布者(publisher)是潜在无限数量的有序元素的生产者。 它根据收到的要求向当前订阅者发布(或发送)元素。
订阅者(subscriber)从发布者那里订阅并接收元素。 发布者向订阅者发送订阅令牌(subscription token)。 使用订阅令牌,订阅者从发布者哪里请求多个元素。 当元素准备就绪时,发布者向订阅者发送多个或更少的元素。 订阅者可以请求更多的元素。 发布者可能有多个来自订阅者的元素待处理请求。
订阅(subscription)表示订阅者订阅的一个发布者的令牌。 当订阅请求成功时,发布者将其传递给订阅者。 订阅者使用订阅令牌与发布者进行交互,例如请求更多的元素或取消订阅。
处理者(processor)充当订阅者和发布者的处理阶段。 Processor
接口继承了Publisher
和Subscriber
接口。 它用于转换发布者——订阅者管道中的元素。 Processor
订阅类型T的数据元素,接收并转换为类型R的数据,并发布变换后的数据。
JDK 9在java.util.concurrent包中提供了一个与响应式流兼容的API,它在java.base模块中。 API由两个类组成:
- Flow
- SubmissionPublisher<T>
Flow
类是final的。 它封装了响应式流Java API和静态方法。 由响应式流Java API指定的四个接口作为嵌套静态接口包含在Flow
类中:
- Flow.Processor<T,R>
- Flow.Publisher<T>
- Flow.Subscriber<T>
- Flow.Subscription
这四个接口包含与上面代码所示的相同的方法。 Flow
类包含defaultBufferSize()
静态方法,它返回发布者和订阅者使用的缓冲区的默认大小。 目前,它返回256。
SubmissionPublisher
类是Flow.Publisher
接口的实现类。 该类实现了AutoCloseable
接口,因此可以使用try-with-resources块来管理其实例。 JDK 9不提供Flow.Subscriber
接口的实现类; 需要自己实现。 但是,SubmissionPublisher
类包含可用于处理此发布者发布的所有元素的consume(Consumer super T> consumer)
方法。
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Flow;
- import java.util.concurrent.SubmissionPublisher;
- import java.util.function.Consumer;
-
- /**
- * 使用java9 Flow中的API实现响应式编程
- */
- public class Reactor03 {
- static class SampleSubScriber
implements Flow.Subscriber { - final Consumer super T> consumer;
- Flow.Subscription subscription;
-
- SampleSubScriber(Consumer super T> consumer) {
- this.consumer = consumer;
- }
-
- @Override
- public void onSubscribe(Flow.Subscription subscription) {
- System.out.println("建立订阅关系");
- this.subscription = subscription;
- // 订阅者只处理两条信息
- subscription.request(2);
- }
-
- @Override
- public void onNext(T item) {
- System.out.println("收到发送者的消息"+ item);
- consumer.accept(item);
- // 消费过后,还可以继续要求发布者发送消息
- // subscription.request(2);
- // 如果不要求发布者发送消息,由于onSubscribe()设置了只处理2条消息,那边发布者就不会继续发布第三条了。
- }
-
- @Override
- public void onError(Throwable throwable) {
- throwable.printStackTrace();
- }
-
- @Override
- public void onComplete() {
-
- }
- }
-
- public static void main(String[] args) {
- SampleSubScriber subScriber = new SampleSubScriber<>(msg -> System.out.println("hello ...... " + msg));
-
- ExecutorService executorService = Executors.newFixedThreadPool(1);
- SubmissionPublisher
submissionPublisher = new SubmissionPublisher<>(executorService, Flow.defaultBufferSize()); - submissionPublisher.subscribe(subScriber);
-
- submissionPublisher.submit(true);
- submissionPublisher.submit(true);
- submissionPublisher.submit(true);
-
- executorService.shutdown();
- }
- }
感谢下述博文的作者:
参考资料: