RxJava介绍及基本原理
随着互联网的迅猛发展,Java已成为最广泛应用于后端开发的语言之一。而在处理异步操作和事件驱动编程方面,传统的Java多线程并不总是最佳选择。这时候,RxJava作为一个基于观察者模式、函数式编程和响应式编程理念的库,为我们提供了一种强大而灵活的解决方案。
简介
RxJava是 ReactiveX
家族的重要一员, ReactiveX
是 Reactive Extensions
的缩写,一般简写为 Rx
。ReactiveX
官方给Rx
的定义是:Rx是一个使用可观察数据流进行异步编程的编程接口。
ReactiveX
不仅仅是一个编程接口,它是一种编程思想的突破,它影响了许多其它的程序库和框架以及编程语言。它拓展了观察者模式
,使你能够自由组合多个异步事件
,而不需要去关心线程
,同步,线程安全
,并发数据以及I/O阻塞
。
RxJava在Java环境下使用,它通过Observable(可观测对象)和Subscriber(订阅者)来实现异步编程模型。Observable可以发射出一系列的数据流,而Subscriber则负责处理这些数据流。利用各种操作符,我们可以对数据流进行变换、过滤、合并等操作,从而完成复杂的异步任务。
GitHub - ReactiveX/RxJava: RxJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.
结论: RxJava是 ReactiveX 在JVM上的一个实现,ReactiveX使用Observable序列组合异步和基于事件的程序的库;是一个 基于事件流、实现异步操作的库。
Observables · ReactiveX文档中文翻译
RxJava 是轻量级的
RxJava尽力做到非常轻巧。它仅关注Observable的抽象和与之相关的高层函数,实现为一个单独的JAR文件。
RxJava 是一个多语言实现
RxJava 支持Java 6或者更新的版本,以及其它的JVM语言如 Groovy, Clojure, JRuby, Kotlin 和 Scala。RxJava 可用于更多的语言环境,而不仅仅是Java和Scala,而且它致力于尊重每一种JVM语言的习惯。
RxJava 第三方库
下面是可与RxJava协作的第三方库:
-
Hystrix - 用于分布式系统的一个延时和容错处理框架
-
Camel RX - 一个用于Apache Camel 的 RxJava 兼容层
-
rxjava-http-tail - 让你可以跟踪HTTP日志,就像使用
tail -f
一样 -
mod-rxvertx - Extension for VertX - 使用 RxJava 封装的VertX库
-
rxjava-jdbc - 使用RxJava流式处理JDBC连接,还支持语句的函数式组合
-
rtree - 使用RxJava实现的一个纯内存的可变的R-tree和R*-tree
使用指南
你可以在Maven Central http://search.maven.org 找到用于Maven, Ivy, Gradle, SBT和其它构建工具需要的二进制文件和依赖信息.
Maven示例:
<dependency><groupId>io.reactivex.rxjava3</groupId><artifactId>rxjava</artifactId><version>3.1.7</version>
</dependency>
RxJava使用三步曲
RxJava的使用可以概括为三个步骤:创建 Observable,定义 Observer 处理数据流,最后订阅(Subscribe)Observable。
创建 Observable
-
可以直接使用 Observable.just() 方法来创建一个发射固定数据项的 Observable;
-
也可以通过 Observable.fromIterable() 方法来创建包含多个数据项的 Observable。
Observable<String> observable = Observable.just("Hello", "World");
定义 Observer
创建一个 Observer 对象并实现它的各个方法。在这些方法中,你可以处理每个发射的数据项、对错误进行处理,或者在数据全部发射完毕时执行一些操作。
Observer<String> observer = new Observer<String>() {@Overridepublic void onSubscribe(Disposable d) {// 在此方法中进行一些初始化操作或资源管理}@Overridepublic void onNext(String s) {// 处理每个发射的数据项System.out.println(s);}@Overridepublic void onError(Throwable e) {// 处理发生的异常情况}@Overridepublic void onComplete() {// 完成所有的数据发射操作}
};
订阅 Observable
observable.subscribe(observer);
RxJava基本原理
生活例子引入
用一个生活例子引入,来介绍 RxJava的基本原理: 顾客到饭店吃饭
RxJava原理介绍
-
RxJava
原理 基于 一种扩展的观察者模式 -
RxJava
的扩展观察者模式中有4个角色:
角色 | 作用 | 类比 |
---|---|---|
被观察者(Observable) | 产生事件 | 顾客 |
观察者(Observer) | 接收事件,并给出响应动作 | 厨房 |
订阅(Subscribe) | 连接 被观察者 & 观察者 | 服务员 |
事件(Event) | 被观察者 & 观察者 沟通的载体 | 菜 |
请结合上述 顾客到饭店吃饭 的生活例子理解:
即RxJava
原理可总结为:被观察者 (Observable)
通过 订阅(Subscribe)
按顺序发送事件 给观察者 (Observer)
, 观察者(Observer)
按顺序接收事件 & 作出对应的响应动作。具体如下图:
代码实现
步骤1:创建被观察者 (**Observable**
** )& 生产事件**
- 即 顾客入饭店 - 坐下餐桌 - 点菜
// 步骤1:创建被观察者 (Observable )& 生产事件
// 即 顾客入饭店 - 坐下餐桌 - 点菜
// 1. 创建被观察者 Observable 对象
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
// create() 是 RxJava 最基本的创造事件序列的方法
// 此处传入了一个 OnSubscribe 对象参数
// 当 Observable 被订阅时,OnSubscribe 的 call() 方法会自动被调用,即事件序列就会依照设定依次被触发
// 即观察者会依次调用对应事件的复写方法从而响应事件
// 从而实现被观察者调用了观察者的回调方法 & 由被观察者向观察者的事件传递,即观察者模式// 2. 在复写的subscribe()里定义需要发送的事件@Overridepublic void subscribe(ObservableEmitter<String> emitter) throws Exception {// 通过 ObservableEmitter类对象产生事件并通知观察者// ObservableEmitter类介绍// 2.1 定义:事件发射器// 2.2 作用:定义需要发送的事件 & 向观察者发送事件emitter.onNext("event01");emitter.onNext("event02");emitter.onNext("event03");emitter.onComplete();}
});
步骤2:创建观察者 (**Observer**
** )并 定义响应事件的行为**
-
即 开厨房 - 确定对应菜式
-
发生的事件类型包括:
Next
事件、Complete
事件 &Error
事件。具体如下:
事件类型 | 定义 | 作用 | 使用规则 | 使用方法 |
---|---|---|---|---|
Next | 普通事件 | 向观察者发送需要响应事件的信号 | 被观聚者可发送无限个Next事件;观察者可接受无限个Next事件 | onNext() |
Complete | 表示所有的事件都已经成功完成(RxJava把所有时间当作队列处理) | 标志 被观察者 不再发送普通事件(Next) | 当被观察者发送了一个Complete事件后,被观察者在Complete事件后的事件将会继续发送,但观察者收到Complete事件后将不再继续接收任何事件;被观察者可以不发送Complete事件。 | onComplete() |
Error | 事件队列异常事件 | 标志 事件处理过程中出现异常(此时队列自动终止,不允许再有事件发出) | 当被观察者发送了一个Error事件后,被观察者在Error事件后的事件将会继续发送,但观察者收到Error事件后将不再继续接收任何事件;被观察者可以不发送Error事件。 | onError() |
// 1. 创建观察者 (Observer )对象
Observer<String> observer = new Observer<String>() {// 2. 创建对象时通过对应复写对应事件方法 从而 响应对应事件// 观察者接收事件前,默认最先调用复写 onSubscribe()@Overridepublic void onSubscribe(Disposable d) {}// 当被观察者生产Next事件 & 观察者接收到时,会调用该复写方法 进行响应@Overridepublic void onNext(String value) {System.out.println("对Next事件作出响应" + value);}// 当被观察者生产Error事件& 观察者接收到时,会调用该复写方法 进行响应@Overridepublic void onError(Throwable e) {}// 当被观察者生产Complete事件& 观察者接收到时,会调用该复写方法 进行响应@Overridepublic void onComplete() {}
};
步骤3:通过订阅(**Subscribe**
)连接观察者和被观察者
- 即 顾客找到服务员 - 点菜 - 服务员下单到厨房 - 厨房烹调
observable.subscribe(observer);
// 或者 observable.subscribe(subscriber);
Subject
来看⼀个⾮常特殊的类型- Subject ,为什么说它特殊呢?原因很简单:它同时充当了Observer和Observable的角色。因为它是一个Observer,它可以订阅一个或多个Observable;又因为它是一个Observable,它可以转发它收到(Observe)的数据,也可以发射新的数据。
由于一个Subject订阅一个Observable,它可以触发这个Observable开始发射数据(如果那个Observable是"冷"的–就是说,它等待有订阅才开始发射数据)。因此有这样的效果,Subject可以把原来那个"冷"的Observable变成"热"的。
Subject的种类
针对不同的场景一共有四种类型的Subject。他们并不是在所有的实现中全部都存在,而且一些实现使用其它的命名约定(例如,在RxScala中Subject被称作PublishSubject)。
AsyncSubject
一个AsyncSubject只在原始Observable完成后,发射来自原始Observable的最后一个值。(如果原始Observable没有发射任何值,AsyncObject也不发射任何值)它会把这最后一个值发射给任何后续的观察者。
AsyncSubject asyncSubject = AsyncSubject.create();
// 发送事件
asyncSubject.onNext(1);
// 订阅
asyncSubject.subscribe(event -> {System.out.println(event);
});
asyncSubject.onNext(3);
// 再次发送事件
asyncSubject.onNext(4);
asyncSubject.onComplete();
// 只会监听到 事件4
PublishSubject
可以不需要初始来进行初始化(也就是可以为空),并且它只会向订阅者发送在订阅之后才接收到的元素。
// 初始化⼀个PublishSubject
PublishSubject publishSubject = PublishSubject.create();
// 发送事件
publishSubject.onNext(1);
// 订阅
publishSubject.subscribe(event -> {System.out.println(event);
});
// 再次发送事件
publishSubject.onNext(2);
publishSubject.onNext(3);
事件1
是无法被订阅的,只接受订阅之后的响应
BehaviorSubject
当观察者订阅BehaviorSubject时,它开始发射原始Observable最近发射的数据(如果此时还没有收到任何数据,它会发射一个默认值),然后继续发射其它任何来自原始Observable的数据。
相关文章:

RxJava介绍及基本原理
随着互联网的迅猛发展,Java已成为最广泛应用于后端开发的语言之一。而在处理异步操作和事件驱动编程方面,传统的Java多线程并不总是最佳选择。这时候,RxJava作为一个基于观察者模式、函数式编程和响应式编程理念的库,为我们提供了…...

nginx目录穿越
测试nginx版本为nginx/1.23.3 location /file {alias /home/;} 在/usr跟目录下新建a.txt测试文件 通过访问 http://{ip}:{端口}/file../test.txt 实现目录穿越 防护:location与alias的值都加上/或不加/...

stl String
构造函数 表达式 效果 string s 生成一个空的 string s string s(str) Copy 构造函数,创建一个 string str 的拷贝 string s(rvStr) Move 构造函数,创建一个 string 并将 rvStr 的内容搬移给 s string s(str,stridx) 将 string str 内“始于位置…...
java通过ffmpeg将wav音频文件转广播音频编码-G.711文件发送
1.直接将wav文件转g711 [ffmpeg.exe -i F:\\tt\\2.wav -f s16le -ar 8k -ac 1 -acodec pcm_s16le F:\\tt\\2pcm.g711] String cmdFfmpeg = "ffmpeg -i "+localUrl...
【Spring】Springmvc执行流程
介绍 SpringMVC是一种基于Spring实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,使用了MVC的架构模式思想,将Web层进行指责解耦,并管理应用所需的生命周期,为简化日常开发,提供了很大便利。 组件 组件Dispatche…...

游戏软件开发与应用软件开发有什么不同呢?
游戏软件开发和应用软件开发是两种不同类型的软件开发,它们在许多方面都有不同之处。以下是它们之间的一些主要区别: 目标用户群体: 游戏软件开发的主要目标是提供娱乐和休闲体验,通常面向广大的游戏玩家群体。游戏软件的设计和开…...

绥化市中心广场焕发新活力:OLED透明拼接屏的奇观展示
OLED透明拼接屏技术在绥化城市的应用引起了广泛关注。 绥化市位于中国东北地区,是黑龙江省的一个重要城市。 该市拥有悠久的历史,历经多个朝代的兴衰。绥化的历史背景赋予了这座城市独特的文化底蕴和魅力。 绥化市内有许多著名景点,其中最…...

JavaScript(CSS)动画引擎汇总
汇总记录前端实现动画相关的库 1、animejs animejs是一个轻量级的JavaScript动画库,具有简单但功能强大的API。 它适用于CSS属性,SVG,DOM属性和JavaScript对象。 官网anime.js • JavaScript animation engine anime.js - a Collection by…...

第九章-线程
初始时,CPU的执行流为进程;当产生了线程概念后,CPU执行流变为了线程,大大增大了一个周期以内进程的执行速度。 线程产生的作用就是为了提速,利用线程提速,原理就是实现多个执行流的伪并行,让处…...

UI设计师岗位的基本职责八篇
UI设计师岗位的基本职责1 职责: 1. 负责公司互联网产品app、web、h5等的用户界面设计工作; 2. 负责运营活动相关的平面及视频设计支持; 3. 负责完成产品相关的界面、图标、动画等的图形界面设计,并参与制定、编写产品视觉设计规范文档; 4. 整理和分…...
【了解一下,单例模式的实现方法--Java】
文章目录 单例模式的实现方法--Java1. 饿汉式单例模式(在类加载时创建实例):2. 懒汉式单例模式(在需要时创建实例,线程不安全):3. 静态内部类方式(懒加载,且线程安全&…...
C++实现enum反射,类似magic_enum,支持enum classes
C实现enum反射,类似magic_enum,支持enum classes 有一个 enum EnumTest { a 1, b, c };首先我们想实现 template <typename T, T N> std::string GetEnumName() {return __PRETTY_FUNCTION__; }这样打印 GetEnumName<EnumTest,static_cast…...

机器学习与模式识别作业----决策树属性划分计算
文章目录 1.决策树划分原理1.1.特征选择1--信息增益1.2.特征选择2--信息增益比1.3.特征选择3--基尼系数 2.决策树属性划分计算题2.1.信息增益计算2.2.1.属性1的信息增益计算2.2.2.属性2的信息增益计算2.2.3.属性信息增益比较 2.2.信息增益比计算2.3.基尼系数计算 1.决策树划分原…...

爬虫破解:解决CSRF-Token反爬问题 - 上海市发展和改革委员会
标题:爬虫破解:解决CSRF-Token反爬问题 - 上海市发展和改革委员会 网址:https://fgw.sh.gov.cn/fgw-interaction-front/biz/projectApproval/home MD5加密:ca7f5c978b1809d15a4b228198814253 需求文档 采集数据如下所示: 解决反爬思路 这里只提供解决思路,解决反爬,…...
网络代理技术的威力:保障安全、保护隐私
在如今高度互联的数字时代,网络代理技术正在崭露头角,为网络工程师和普通用户提供了保障网络安全和隐私的强大工具。本文将深入探讨Socks5代理、IP代理以及它们在网络安全、爬虫开发和HTTP协议中的关键作用。 1. Socks5代理:多功能的网络中继…...

【STM32 中断】
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 STM32中断 前言一、STM32的中断如何?如何管理这么复杂的中断?实际优先级如下怎么使用呢? 二、使用步骤1.引入库函数先分组,怎么…...

TensorFlow入门(十二、分布式训练)
1、按照并行方式来分 ①模型并行 假设我们有n张GPU,不同的GPU被输入相同的数据,运行同一个模型的不同部分。 在实际训练过程中,如果遇到模型非常庞大,一张GPU不够存储的情况,可以使用模型并行的分布式训练,把模型的不同部分交给不同的GPU负责。这种方式存在一定的弊端:①这种方…...

在React中,什么是props(属性)?如何向组件传递props?
聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...

java 每种设计模式的作用,与应用场景
文章目录 前言java 每种设计模式的作用,与应用场景 前言 如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。 而且听说点赞的人每天的运气都不会太差,实在白嫖的话࿰…...

Appium问题及解决:打开Appium可视化界面,点击搜索按钮,提示inspectormoved
打开Appium可视化界面,点击搜索按钮,提示inspectorMoved,那么如何解决这个问题呢? 搜索了之后发现,由于高版本Appium(从1.22.0开始)的服务和元素查看器分离,所以还需要下载Appium In…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...

代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...

海云安高敏捷信创白盒SCAP入选《中国网络安全细分领域产品名录》
近日,嘶吼安全产业研究院发布《中国网络安全细分领域产品名录》,海云安高敏捷信创白盒(SCAP)成功入选软件供应链安全领域产品名录。 在数字化转型加速的今天,网络安全已成为企业生存与发展的核心基石,为了解…...

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践,很多人以为AI已经强大到不需要程序员了,其实不是,AI更加需要程序员,普通人…...

云原生安全实战:API网关Envoy的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关 作为微服务架构的统一入口,负责路由转发、安全控制、流量管理等核心功能。 2. Envoy 由Lyft开源的高性能云原生…...