关于响应式编程
来源:互联网 发布:绝仁弃义 知乎 编辑:程序博客网 时间:2024/05/21 22:37
近来响应式编程成为一种流行的模式,涌现出很多支持各种编程语言的库和框架和相关的博文文章。像Facebook,SoundCloud,Microsoft,Netflix等大公司也开始支持和使用这种模式。所以我们这些程序员需要弄清楚关于响应式编程的一些问题。为什么人们会对于响应式编程如此狂热?什么事响应式编程?使用它会对于我们的项目有哪些帮助?我们应该去学习和使用它吗?
同时,Java作为一门支持多线程、高效可靠的流行编程语言,被广泛的应用于建立复杂的应用程序(搜索引擎,通过数据库为复杂的网络应用提供支持的服务端应用等)。但是Java也有一些令人诟病的地方——仅使用内置工具很难写一些简单的并发程序,使用Java编程会经常写大量的样式化代码。并且如果你使用异步方式(例如使用Future),会很容易进入“CallBack hell”,当然几乎所有的编程语言都有这个通病。
CallBack hell:Java进行异步编程的时候往往会使用CallBack的方式来通知结果,在复杂的业务中会因为CallBack的层层嵌套导致整个代码难以理解。
换句话说,Java足够强大能够让你完成一些好的应用,但是也会遇到困扰。好消息是已经有一个解决问题的办法——使用相应式编程。
这里我们将会介绍RxJava这个项目,一个开源的基于Java语言的相应式编程实现。使用RxJava写代码跟通常的思考方式有一些不同,但是会让你能够用简单且结构鲜明的代码来处理复杂的业务逻辑。
这里我们会介绍:
- 什么事响应式编程
- 学习和使用响应式编程的原因
- 开始使用RxJava和熟悉这个模式框架
- 一个RxJava的小例子
什么事响应式编程?
响应式编程是一种解决关于事件传播的范式。换句话说,如果一个程序把所有数据的变化事件广播给对它感兴趣的部分(用户、其他程序、其他组件,以及下属部分),那么这个程序就可以称为一个响应式程序。
一个更简单的例子使用是Microsoft Excel。如果你在A1单元格输入一个数字,也在在B1输入一个数字,并且设置C1的内容为SUM(A1, B1)
,一旦A1或者是B1出现变化,那么C1将会立即更新他们的和。
我们把这种叫做响应式求和。
响应式跟传统的方式不同点有哪些呢?我们可以看看下面的例子:
int a = 4;int b = 5;int c = a + b;System.out.println("" + c);//9a = 6;System.out.println("" + c);//还是9// c虽然是a和b的和,但是我们改变a的值后,c的值并没有随之改变。
这个例子简单介绍了响应式编程的意义。当然我们有许多办法能够解决这个问题,但是也有一些问题需要解决。
为什么我们需要响应式编程?
回答这个问题的最简单方式是思考目前我们开发项目所面临的需求。
10-15年之前,网站出现故障或者是相应很慢是一种正常的现象,但是现在必须保证能够24*7在线可用,并且必须快速响应。一旦变慢或者不可用,使用者会倾向于转向其他的服务。在今天响应慢就是不可用或者出问题了。现在我们处理的是大量数据,并且需要提供快速的服务和处理。
过去网络请求的失败并不是什么大事,但是现在我们必须处理容错和给用户提供合理的原因信息。
过去,我们一般是开发简单的桌面程序,现在我们需要处理的是要求快速响应的网络应用。并且大多数情况,这些应用需要跟大量的远程服务进行通信。
如果我们想要我们的产品具有竞争力,就必须满足以上的所有需求。换句话说,我们必须做好以下内容:
- 模块化/动态化:这可以帮助我们的产品24*7可用。因为模块是可以在不当机的情况下上线和下线的。并且这种方式,也利于我们项目的架构能够解决随着规模增加更好代码管理的问题。
- 可扩展:这种方式使我们能够处理大数据和大量的请求。
- 容错机制:这可以是系统更稳定。
- 快速响应:意味着系统运行快速和高度可用。
让我们思考如何才能解决上面的需求呢:
- 如果我们的系统是事件驱动的那么就可以实现模块化。我们可以把整个系统划分为小的模块组件,并通过通知来进行组件间通信。这样我们可以响应处理通知表示的系统数据流。
- 可扩展意味着能够正常载入来响应持续增长的数据。
- 对失败和错误进行响应能够增加系统的稳定性。
- 快速响应就是能够迅速对于用户的活动进行反馈。
介绍RxJava
要进行响应式编程,我们需要一个库或者是一种特殊的编程语言,毕竟自己实现对于大多数人是一件非常困难的任务。并且Java并不是一门真正的相应式编程语言(虽然提供了java.util.Observable
,但是功能太局限)。Java是一门静态,面向对象的语言,我们要完成一些功能需要写一些模式代码(简单的Java Bean等)。但是目前有一个支持Java的响应式编程库——RxJava。RxJava是一个由Netflix最初建立的一个开源项目,目前已经有很多人为这个项目贡献代码进行完善。
下载和配置RxJava
你可以从Github来下载源码,自己进行打包(https://github.com/ReactiveX/RxJava)。RxJava不依赖其他的库,支持Java8的lambda。有非常好的Javadoc和Github wiki,你可以从中查找资料和学习。你可以通过下面的方式下载和建立:
$ git clone git@github.com:ReactiveX/RxJava.git$ cd RxJava/$ ./gradlew build
当然我们更常用的是只下载已经生成好的jar文件,这里我们以1.0.14版本为例。
如果你使用Maven,你可以通过在pom.xml
中添加RxJava作为一个依赖:
<dependency> <groupId>io.reactivex</groupId> <artifactId>rxjava</artifactId> <version>1.0.14</version></dependency>
使用Gradle则需要配置你的build.gradle
,添加下面的内容:
dependencies { ... compile 'io.reactivex:rxjava:1.0.14' ...}
一个使用RxJava实现两个数相加的简单例子
public static void main(String[] args) { ConnectableObservable<String> cob = getConnect(System.in); Observable<Double> a = varInput("a", cob); Observable<Double> b = varInput("b", cob); reactSum(a, b); cob.connect();}static ConnectableObservable<String> getConnect(InputStream inputStream) { final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); return Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { String line; if (subscriber.isUnsubscribed()) return; try { while (!subscriber.isUnsubscribed() && (line = reader.readLine()) != null) { if (line.equals("exit")) { break; } subscriber.onNext(line); } if (!subscriber.isUnsubscribed()) { subscriber.onCompleted(); } } catch (IOException e) { e.printStackTrace(); subscriber.onError(e); } } } ).publish();}static Observable<Double> varInput(String tag, Observable<String> observable) { final Pattern pattern = Pattern.compile("^\\s*" + tag + "\\s*[:|=]\\s*(-?\\d+\\.?\\d*)$"); return observable.map(new Func1<String, Matcher>() { @Override public Matcher call(String s) { return pattern.matcher(s); } }) .filter(new Func1<Matcher, Boolean>() { @Override public Boolean call(Matcher matcher) { return matcher.find(); } }) .map(new Func1<Matcher, String>() { @Override public String call(Matcher matcher) { return matcher.group(1); } }) .map(new Func1<String, Double>() { @Override public Double call(String s) { return Double.parseDouble(s); } });}static void reactSum(Observable<Double> a, Observable<Double> b) { Observable.combineLatest(a, b, new Func2<Double, Double, Double>() { @Override public Double call(Double aDouble, Double aDouble2) { return aDouble + aDouble2; } }) .subscribe(new Subscriber<Double>() { @Override public void onCompleted() { System.out.println("onComplete"); } @Override public void onError(Throwable e) { System.out.println("onError:" + e.getMessage()); } @Override public void onNext(Double aDouble) { System.out.println("a + b is:" + aDouble); } });}
运行结果可能如下:
a:1b:3a + b is:4.0a:5a + b is:8.0exitonComplete
如果搭配Java8的lambda,程序会更加的简洁。这里我们暂时先不使用lambda。
- 关于响应式编程
- 响应式编程:理解响应式编程
- 响应式编程介绍
- ReactiveX--响应式编程
- 响应式编程Rxjava
- 响应式编程介绍
- 响应式编程
- IOS-响应式编程
- 函数响应式编程
- rxandroid响应式编程
- 响应式编程
- 谈谈响应式编程
- RxJava响应式编程
- 响应式函数编程
- RXJAVA响应式编程
- 响应式编程简介
- 响应式编程
- 响应式编程笔记
- 【图论】匈牙利算法模板
- spring 一些注解
- 微信分享透明背景图片背景变黑
- Tomcat多域名配置
- 为什么groupbykey是宽依赖
- 关于响应式编程
- 动画切换数字,字符view
- 想成为嵌入式程序员应知道的0x10个基本问题
- 1-3-1页面布局实例
- HDOJ 1060 Leftmost Digit
- flex 弹性和模型 学习手记
- 数组中只出现一次的元素
- 如何把ppt转换成word文档格式
- 数据仓库的一些基本知识