响应式编程是一种面向数据流和变化传播的编程范式.
异步编程的几种方式
一般来说 提高程序性能有以下两种方法
并行化
使用更多线程和硬件资源提高资源利用率
提高资源利用率
通常, 程序员们一开始都是以阻塞代码来实现业务需求. 直到出现性能瓶颈, 这时候 通常的做法是引入一些额外的线程 运行类似的阻塞代码 但这种扩展方式会引入资源竞争&并发问题
通常通过编写异步非阻塞问题可以解决上面的问题 提高资源利用率 Java原生提供了两种异步编程模型: Callback/Future
Callback
回调几乎没有组合能力,在复杂业务场景下, 每个函数调用都需要调用一个Callback, 缩进会一直增加, 很快就会导致代码难以阅读和维护(业界俗称为“Callback Hell”)。另外 如果想要处理异常 还得额外传入一个处理异常的Callback.
Future
Future对象比回调好一点,但它们在组合方面仍然表现不佳
尽管jdk8 里有了 CompletableFuture. 将多个 Future对象编排在一起是可行的,但也并不容易。
Reactive
Callback&Future 是最简单最基础的响应式. 但他们面向的都是单值
协程
上述三种异步编程(Callback/Future/Reactive)的难点 正如 Dean Gaudet(Apache开发者)所说:“其内在的复杂性——将线性思维分解成一堆回调的负担(breaking up linear thought into a bucketload of callbacks)——仍然存在, 协程旨在使用同步阻塞编程模型解决传统的异步编程模式(Callback/Future/Reactive), 以更接近自然编程模式(线性思维).
在了解协程之前, 我们先来看一下CPS(Continuation-passing style)
CPS-(Continuation-passing style)
CPS是函数式编程中一个古老的概念, 最初是在1970年代作为一种编程风格出现, 现在, CPS作为反应式系统的编程风格而被再次发掘出来.
首先, 我们先来看一下一般的编程风格.
上面的代码重构成CPS风格的代码则如下(这个过程通常称为CPS变换):
CPS变换即将程序的后半部分构造成一个 Continuation, 通过函数参数进行传递, 在未来某个时刻调用它, 以运行程序的后半部分, ’contionuation‘ 一般晦涩的翻译成 “计算续体”, 通常也叫做 “程序的剩下部分”. 大家这里也能看到, contionuation 和上面的 Callback 其实很像, 只不过换了一个叫法.
Callback/Future/Reactive 本质上都是在手动构造 contionuation, 进行CPS变换, 而协程则是通过一些方式进行自动CPS变换, 减少我们的编程负担.
java中实现协程的几种方式
- async/await
-
jvm层面内置协程
在阻塞调用的地方 jvm内部进行CPS变换
业界趋势&思考
在异步编程方向上, 现在java领域里比较主流的方向有两个
- 反应式编程
- 协程
当然反应式与协程并不是完全对立关系, 虽然在简单的异步场景下,协程会让响应式编程的适用变小. 虽然反应式编程是异步编程的一个子集, 但它不仅仅只是为了异步编程. 他还具有以下几个重要特性
- 针对复杂异步流的编排以及组合能力
- 与并发无关的高层次抽象