(20)操作符熔合——响应式Spring的道法术器

本系列其他文章见:《响应式Spring的道法术器》
前情提要:响应式流 | Reactor3快速上手 | 深入理解响应式流规范

2.10 操作符熔合

操作符熔合是响应式编程领域比较前沿的研究话题,目的在于通过将多个操作符以某种方式熔合起来,以达到优化的效果,进而降低开销(比如执行时间,内存)。

以下部分内容参考了 Dávid Karnok 的 Operator-fusion(part1part2)。

2.10.1 分代的概念

首先介绍一下关于响应式编程库的分代的概念。直至现在,响应式编程库及相关概念仍然在不断的更新和升级。作者根据自己在响应式编程领域的研究经验,将响应式编程库分为四代。

第零代

起初的响应式编程工具主要包括类似java.util.Observable的基于订阅者模式的API,以及那些基于回调的API,如 Swing/AWT/Android 中的 addXXXListener。但是两者都有些共同的不足:不方便组合(就像我们前边的操作链那样)。

第一代

后来,Erik Meijer 和他在微软的团队解决了难以组合的问题,从而诞生了第一代响应式编程库:2010 年左右的 Rx.NET,2011 年的 Reactive4Java,以及 2013 年早期的 RxJava。

其他的语言也陆续基于 Rx.NET 的架构开发了类似的库,但很快大家发现这种架构存在的问题。第一个问题是,最初的 IObservable/IObserver 在纯单线程中实现后,如果使用类似 take() 的操作符,之后的序列无法取消。Rx.NET 通过在诸如 range() 的数据源进行异步,绕开了这个问题。

第二个问题是,当生产者与消费者之间存在一个异步边界(不在同一线程)时,如果消费者消费数据的速度不够快,也会导致问题。这时消费者的代码会非常繁琐,这就是我们前面多次提到的 backpressure 问题。

第二代

RxJava团队针对上边的两个问题设计了一套新的架构。

首先是引入了 Subscriber 类,它能通过 isUnsubscribed() 方法判断是否取消订阅,数据源或者操作符发在数据之前都会调用该方法进行检查。

然后,backpressure 的问题则通过双方协调的方式解决,利用 Producer 接口,Subscriber 告知上游自己能处理数据的量(request() 方法)。

第三个改进是 lift() 函数,使用它可以直接在 Subscriber 之间进行函数式的变换。几乎所有操作符的实现都被重写,改成了利用新的 Operator 接口和 lift() 函数。

第三代

后边的故事本系列文章的读者就熟悉了。响应式编程的兴起使得大家意识到互相之间要兼容。于是来自多个公司的工程师们聚在了一起,设计了一套响应式流(Reactive-Streams)规范,主要成果是 4 个接口,30 条关于这几个接口的规则,以及这几个接口里的 7 个方法。

Reactive-Streams 规范使得响应式编程实现库之间可以相互兼容,从而能够随意切换具体的实现库。

因此基于响应式流的实现属于第三代,它的实现包括 RxJava 2.x,Project Reactor 和 Akka-Streams等。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值