揭秘 RxJava 操作符组合模块:从使用到源码的深度剖析
一、引言
在现代软件开发中,响应式编程的概念越来越受到开发者的青睐。RxJava 作为 Java 平台上一个强大的响应式编程库,提供了丰富的操作符,能够帮助开发者高效地处理异步事件流。其中,操作符组合模块是 RxJava 的核心功能之一,它允许开发者将多个操作符组合在一起,构建出复杂而强大的数据流处理逻辑。
本文将深入分析 RxJava 操作符组合模块的使用原理,从基础的操作符组合示例开始,逐步深入到源码级别,详细解读每一个关键步骤和核心逻辑。通过本文的学习,你将对 RxJava 操作符组合模块有更深入的理解,能够更加熟练地运用这些操作来解决实际开发中的问题。
二、RxJava 操作符组合基础
2.1 操作符组合的概念
操作符组合是指将多个 RxJava 操作符按照一定的顺序组合在一起,形成一个链式调用,从而实现复杂的数据流处理逻辑。每个操作符都会对输入的数据流进行特定的转换或处理,并将处理后的数据流传递给下一个操作符。通过操作符组合,我们可以将多个简单的操作组合成一个复杂的操作,提高代码的可读性和可维护性。
2.2 操作符组合的重要性
操作符组合在 RxJava 中具有重要的意义。它使得开发者可以将复杂的数据流处理逻辑分解为多个简单的步骤,每个步骤由一个操作符来完成。这样,代码的结构更加清晰,易于理解和维护。同时,操作符组合还可以提高代码的复用性,不同的操作符可以根据需要进行组合,以满足不同的业务需求。
2.3 常用操作符组合场景
在实际开发中,操作符组合有很多常见的场景,例如:
- 数据过滤和转换:通过
filter()和map()操作符组合,对数据流进行过滤和转换。 - 数据合并和拆分:使用
merge()和flatMap()操作符组合,将多个数据流合并为一个,或者将一个数据流拆分为多个。 - 错误处理和重试:结合
onErrorReturn()和retry()操作符,处理数据流中的错误并进行重试。
三、常见操作符组合示例及原理分析
3.1 map() 和 filter() 操作符组合
3.1.1 示例代码
import io.reactivex.rxjava3.core.Observable;
public class MapAndFilterExample {
public static void main(String[] args) {
// 创建一个 Observable,发射 1 到 5 的整数
Observable<Integer> source = Observable.just(1, 2, 3, 4, 5);
// 使用 map() 操作符将每个整数乘以 2
Observable<Integer> mapped = source.map(item -> item * 2);
// 使用 filter() 操作符过滤出大于 5 的整数
Observable<Integer> filtered = mapped.filter(item -> item > 5);
// 订阅并打印结果
filtered.subscribe(System.out::println);
}
}
3.1.2 源码分析
首先,我们来看 map() 操作符的源码:
// Observable 类中的 map() 方法
public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
// 检查传入的 mapper 函数是否为 null
ObjectHelper.requireNonNull(mapper, "mapper is null");
// 创建一个 MapObservable 对象,并将当前 Observable 和 mapper 函数作为参数传入
return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
}
// ObservableMap 类的定义
final class ObservableMap<T, U> extends AbstractObservableWithUpstream<T, U> {
// 存储 mapper 函数
final Function<? super T, ? extends U> function;
ObservableMap(ObservableSource<T> source, Function<? super T, ? extends U> function) {
// 调用父类的构造函数,传入原始的 Observable
super(source);
// 初始化 mapper 函数
this.function = function;
}
@Override
protected void subscribeActual(Observer<? super U> observer) {
// 创建一个 MapObserver 对象,并将原始的 observer 和 mapper 函数作为参数传入
source.subscribe(new MapObserver<T, U>(observer, function));
}
// MapObserver 类的定义
static final class MapObserver<T, U> extends BasicFuseableObserver<T, U> {
// 存储 mapper 函数
final Function<? super T, ? extends U> mapper;
MapObserver(Observer<? super U> actual, Function<? super T, ? extends U> mapper) {
// 调用父类的构造函数,传入原始的 observer
super(actual);
// 初始化 mapper 函数
this.mapper = mapper;
}
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
downstream.onNext(null);
return;
}
U v;
try {
// 调用 mapper 函数对输入的数据进行转换
v = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
} catch (Throwable ex) {
fail(ex);
return;
}
// 将转换后的数据传递给下游的 observer
downstream.onNext(v);
}
// 省略其他方法
}
}
在 map() 操作符中,首先创建了一个 ObservableMap 对象,它继承自 AbstractObservableWithUpstream。在 subscribeActual() 方法中,创建了一个 MapObserver 对象,并将其订阅到原始的 Observable 上。当原始的 Observable 发射数据时,MapObserver 的 onNext() 方法会被调用,在该方法中,会调用 mapper 函数对输入的数据进行转换,并将转换后的数据传递给下游的 observer。
接下来,我们看 filter() 操作符的源码:
// Observable 类中的 filter() 方法
public final Observable<T> filter(Predicate<? super T> predicate) {
// 检查传入的 predicate 函数是否为 null
ObjectHelper.requireNonNull(predicate, "predicate is null");
// 创建一个 FilterObservable 对象,并将当前 Observable 和 predicate 函数作为参数传入
return RxJavaPlugins.onAssembly(new ObservableFilter<T>(this, predicate));
}
// ObservableFilter 类的定义
final class ObservableFilter<T> extends AbstractObservableWithUpstream<T, T> {
// 存储 predicate 函数
final Predicate<? super T> predicate;
ObservableFilter(ObservableSource<T> source, Predicate<? super T> predicate) {
// 调用父类的构造函数,传入原始的 Observable
super(source);
// 初始化 predicate 函数
this.predicate = predicate;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
// 创建一个 FilterObserver 对象,并将原始的 observer 和 predicate 函数作为参数传入
source.subscribe(new FilterObserver<T>(observer, predicate));
}
// FilterObserver 类的定义
static final class FilterObserver<T> extends BasicFuseableObserver<T, T> {
// 存储 predicate 函数
final Predicate<? super T> filter;
FilterObserver(Observer<? super T> actual, Predicate<? super T> filter) {
// 调用父类的构造函数,传入原始的 observer
super(actual);
// 初始化 predicate 函数
this.filter = filter;
}
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
downstream.onNext(null);
return;
}
boolean b;
try {
// 调用 predicate 函数对输入的数据进行过滤判断
b = filter.test(t);
} catch (Throwable ex) {
fail(ex);
return;
}
if (b) {
// 如果满足过滤条件,将数据传递给下游的 observer
downstream.onNext(t);
}
}
// 省略其他方法
}
}
在 filter() 操作符中,创建了一个 ObservableFilter 对象,它也继承自 AbstractObservableWithUpstream。在 subscribeActual() 方法中,创建了一个 FilterObserver 对象,并将其订阅到原始的 Observable 上。当原始的 Observable 发射数据时,FilterObserver 的 onNext() 方法会被调用,在该方法中,会调用 predicate 函数对输入的数据进行过滤判断,如果满足条件,则将数据传递给下游的 observer。
3.2 flatMap() 和 concatMap() 操作符组合
3.2.1 示例代码
import io.reactivex.rxjava3.core.Observable;
import java.util.concurrent.TimeUnit;
public class FlatMapAndConcatMapExample {
public static void main(String[] args) {
// 创建一个 Observable,发射 1 到 3 的整数
Observable<Integer> source = Observable.just(1, 2, 3);
// 使用 flatMap() 操作符将每个整数转换为一个新的 Observable
Observable<Integer> flatMapped = source.flatMap(item ->
Observable.range(item, 2).delay(100, TimeUnit.MILLISECONDS)
);
// 使用 concatMap() 操作符将每个整数转换为一个新的 Observable
Observable<Integer> concatMapped = source.concatMap(item ->
Observable.range(item, 2).delay(100, TimeUnit.MILLISECONDS)
);
// 订阅 flatMap() 结果并打印
flatMapped.subscribe(item -> System.out.println("FlatMap: " + item));
try {
// 等待一段时间
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 订阅 concatMap() 结果并打印
concatMapped.subscribe(item -> System.out.println("ConcatMap: " + item));
}
}
3.2.2 源码分析
首先,我们来看 flatMap() 操作符的源码:
// Observable 类中的 flatMap() 方法
public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper) {
// 调用重载的 flatMap() 方法,传入 mapper 函数和默认参数
return flatMap(mapper, false, Integer.MAX_VALUE);
}
// Observable 类中的重载 flatMap() 方法
public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper,
boolean delayErrors, int maxConcurrency) {
// 检查传入的 mapper 函数是否为 null
ObjectHelper.requireNonNull(mapper, "mapper is null");
// 创建一个 ObservableFlatMap 对象,并将当前 Observable、mapper 函数、delayErrors 和 maxConcurrency 作为参数传入
return RxJavaPlugins.onAssembly(new ObservableFlatMap<T, R>(this, mapper, delayErrors, maxConcurrency));
}
// ObservableFlatMap 类的定义
final class ObservableFlatMap<T, U> extends AbstractObservableWithUpstream<T, U> {
// 存储 mapper 函数
final Function<? super T, ? extends ObservableSource<? extends U>> mapper;
// 存储是否延迟错误处理的标志
final boolean delayErrors;
// 存储最大并发数
final int maxConcurrency;
ObservableFlatMap(ObservableSource<T> source,
Function<? super T, ? extends ObservableSource<? extends U>> mapper,
boolean delayErrors, int maxConcurrency) {
// 调用父类的构造函数,传入原始的 Observable
super(source);
// 初始化 mapper 函数
this.mapper = mapper;
// 初始化是否延迟错误处理的标志
this.delayErrors = delayErrors;
// 初始化最大并发数
this.maxConcurrency = maxConcurrency;
}
@Override
protected void subscribeActual(Observer<? super U> t) {
if (ObservableScalarXMap.tryScalarXMapSubscribe(source, t, mapper)) {
return;
}
// 创建一个 MergeObserver 对象,并将原始的 observer、mapper 函数、delayErrors 和 maxConcurrency 作为参数传入
source.subscribe(new MergeObserver<T, U>(t, mapper, delayErrors, maxConcurrency));
}
// MergeObserver 类的定义(部分代码)
static final class MergeObserver<T, U> extends AtomicInteger implements Disposable, Observer<T> {
// 省略部分属性定义
MergeObserver(Observer<? super U> actual,
Function<? super T, ? extends ObservableSource<? extends U>> mapper,
boolean delayErrors, int maxConcurrency) {
// 初始化相关属性
this.actual = actual;
this.mapper = mapper;
this.delayErrors = delayErrors;
this.maxConcurrency = maxConcurrency;
this.observers = new InnerObserver[maxConcurrency == Integer.MAX_VALUE ? 16 : maxConcurrency];
}
@Override
public void onNext(T t) {
// 省略部分代码
ObservableSource<? extends U> p;
try {
// 调用 mapper 函数将输入的数据转换为一个新的 ObservableSource
p = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper returned a null ObservableSource");
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
cancel();
actual.onError(ex);
return;
}
// 处理新的 ObservableSource
subscribeInner(p);
}
// 省略其他方法
}
}
在 flatMap() 操作符中,首先创建了一个 ObservableFlatMap 对象。在 subscribeActual() 方法中,创建了一个 MergeObserver 对象,并将其订阅到原始的 Observable 上。当原始的 Observable 发射数据时,MergeObserver 的 onNext() 方法会被调用,在该方法中,会调用 mapper 函数将输入的数据转换为一个新的 ObservableSource,然后对这个新的 ObservableSource 进行订阅处理。flatMap() 操作符会并发地处理这些新的 ObservableSource,可能会导致数据发射的顺序不确定。
接下来,我们看 concatMap() 操作符的源码:
// Observable 类中的 concatMap() 方法
public final <R> Observable<R> concatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper) {
// 调用重载的 concatMap() 方法,传入 mapper 函数和默认参数
return concatMap(mapper, Integer.MAX_VALUE);
}
// Observable 类中的重载 concatMap() 方法
public final <R> Observable<R> concatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper, int prefetch) {
// 检查传入的 mapper 函数是否为 null
ObjectHelper.requireNonNull(mapper, "mapper is null");
// 创建一个 ObservableConcatMap 对象,并将当前 Observable、mapper 函数和 prefetch 作为参数传入
return RxJavaPlugins.onAssembly(new ObservableConcatMap<T, R>(this, mapper, prefetch));
}
// ObservableConcatMap 类的定义
final class ObservableConcatMap<T, U> extends AbstractObservableWithUpstream<T, U> {
// 存储 mapper 函数
final Function<? super T, ? extends ObservableSource<? extends U>> mapper;
// 存储预取数量
final int prefetch;
ObservableConcatMap(ObservableSource<T> source,
Function<? super T, ? extends ObservableSource<? extends U>> mapper,
int prefetch) {
// 调用父类的构造函数,传入原始的 Observable
super(source);
// 初始化 mapper 函数
this.mapper = mapper;
// 初始化预取数量
this.prefetch = prefetch;
}
@Override
protected void subscribeActual(Observer<? super U> t) {
if (ObservableScalarXMap.tryScalarXMapSubscribe(source, t, mapper)) {
return;
}
// 创建一个 ConcatMapObserver 对象,并将原始的 observer、mapper 函数和 prefetch 作为参数传入
source.subscribe(new ConcatMapObserver<T, U>(t, mapper, prefetch));
}
// ConcatMapObserver 类的定义(部分代码)
static final class ConcatMapObserver<T, U> extends AtomicInteger implements Observer<T>, Disposable {
// 省略部分属性定义
ConcatMapObserver(Observer<? super U> actual,
Function<? super T, ? extends ObservableSource<? extends U>> mapper,
int prefetch) {
// 初始化相关属性
this.actual = actual;
this.mapper = mapper;
this.prefetch = prefetch;
this.queue = new SpscLinkedArrayQueue<T>(prefetch);
}
@Override
public void onNext(T t) {
// 省略部分代码
ObservableSource<? extends U> p;
try {
// 调用 mapper 函数将输入的数据转换为一个新的 ObservableSource
p = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper returned a null ObservableSource");
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
cancel();
actual.onError(ex);
return;
}
// 处理新的 ObservableSource
drain();
if (!done) {
sources.offer(p);
if (getAndIncrement() == 0) {
drain();
}
}
}
// 省略其他方法
}
}
在 concatMap() 操作符中,创建了一个 ObservableConcatMap 对象。在 subscribeActual() 方法中,创建了一个 ConcatMapObserver 对象,并将其订阅到原始的 Observable 上。当原始的 Observable 发射数据时,ConcatMapObserver 的 onNext() 方法会被调用,在该方法中,会调用 mapper 函数将输入的数据转换为一个新的 ObservableSource,然后将这些新的 ObservableSource 按顺序进行处理,保证数据发射的顺序和原始数据的顺序一致。
3.3 zip() 和 combineLatest() 操作符组合
3.3.1 示例代码
import io.reactivex.rxjava3.core.Observable;
import java.util.concurrent.TimeUnit;
public class ZipAndCombineLatestExample {
public static void main(String[] args) {
// 创建第一个 Observable,每隔 1 秒发射一个整数
Observable<Integer> source1 = Observable.interval(1, TimeUnit.SECONDS)
.map(item -> (int) item)
.take(3);
// 创建第二个 Observable,每隔 2 秒发射一个整数
Observable<Integer> source2 = Observable.interval(2, TimeUnit.SECONDS)
.map(item -> (int) item)
.take(2);
// 使用 zip() 操作符将两个 Observable 组合
Observable<String> zipped = Observable.zip(source1, source2, (item1, item2) -> "Zip: " + item1 + " - " + item2);
// 使用 combineLatest() 操作符将两个 Observable 组合
Observable<String> combined = Observable.combineLatest(source1, source2, (item1, item2) -> "Combine: " + item1 + " - " + item2);
// 订阅 zip() 结果并打印
zipped.subscribe(System.out::println);
try {
// 等待一段时间
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 订阅 combineLatest() 结果并打印
combined.subscribe(System.out::println);
}
}
3.3.2 源码分析
首先,我们来看 zip() 操作符的源码:
// Observable 类中的 zip() 方法
public static <T1, T2, R> Observable<R> zip(ObservableSource<? extends T1> source1,
ObservableSource<? extends T2> source2,
BiFunction<? super T1, ? super T2, ? extends R> zipper) {
// 检查传入的参数是否为 null
ObjectHelper.requireNonNull(source1, "source1 is null");
ObjectHelper.requireNonNull(source2, "source2 is null");
ObjectHelper.requireNonNull(zipper, "zipper is null");
// 创建一个 ZipObservable 对象,并将两个 ObservableSource 和 zipper 函数作为参数传入
return RxJavaPlugins.onAssembly(new ObservableZip<T1, T2, R>(new ObservableSource[]{source1, source2}, zipper, false, bufferSize()));
}
// ObservableZip 类的定义
final class ObservableZip<T, R> extends Observable<R> {
// 存储多个 ObservableSource
final ObservableSource<? extends T>[] sources;
// 存储 zipper 函数
final Function<? super Object[], ? extends R> zipper;
// 存储是否延迟错误处理的标志
final boolean delayError;
// 存储缓冲区大小
final int bufferSize;
ObservableZip(ObservableSource<? extends T>[] sources,
Function<? super Object[], ? extends R> zipper,
boolean delayError, int bufferSize) {
// 初始化相关属性
this.sources = sources;
this.zipper = zipper;
this.delayError = delayError;
this.bufferSize = bufferSize;
}
@Override
protected void subscribeActual(Observer<? super R> t) {
// 创建一个 ZipCoordinator 对象,并将原始的 observer、zipper 函数、delayError 和 bufferSize 作为参数传入
ZipCoordinator<T, R> zc = new ZipCoordinator<T, R>(t, zipper, sources.length, delayError, bufferSize);
zc.subscribe(sources);
}
// ZipCoordinator 类的定义(部分代码)
static final class ZipCoordinator<T, R> implements Disposable {
// 省略部分属性定义
ZipCoordinator(Observer<? super R> actual,
Function<? super Object[], ? extends R> zipper,
int count, boolean delayError, int bufferSize) {
// 初始化相关属性
this.actual = actual;
this.zipper = zipper;
this.delayError = delayError;
this.bufferSize = bufferSize;
this.observers = new ZipObserver[count];
this.queue = new SpscLinkedArrayQueue[count];
}
void subscribe(ObservableSource<? extends T>[] sources) {
ZipObserver<T, R>[] s = observers;
int len = s.length;
for (int i = 0; i < len; i++) {
// 创建一个 ZipObserver 对象,并将当前的 ZipCoordinator 和索引作为参数传入
s[i] = new ZipObserver<T, R>(this, i);
}
lazySet(0);
actual.onSubscribe(this);
for (int i = 0; i < len; i++) {
if (disposed) {
return;
}
// 将每个 ZipObserver 订阅到对应的 ObservableSource 上
sources[i].subscribe(s[i]);
}
}
// 省略其他方法
}
// ZipObserver 类的定义(部分代码)
static final class ZipObserver<T, R> implements Observer<T> {
// 省略部分属性定义
ZipObserver(ZipCoordinator<T, R> parent, int index) {
// 初始化相关属性
this.parent = parent;
this.index = index;
this.queue = new SpscLinkedArrayQueue<T>(parent.bufferSize);
}
@Override
public void onNext(T t) {
// 将接收到的数据放入队列中
queue.offer(t);
// 尝试合并数据
parent.drain();
}
// 省略其他方法
}
}
在 zip() 操作符中,创建了一个 ObservableZip 对象。在 subscribeActual() 方法中,创建了一个 ZipCoordinator 对象,并调用其 subscribe() 方法,将每个 ZipObserver 订阅到对应的 ObservableSource 上。当每个 ObservableSource 发射数据时,ZipObserver 的 onNext() 方法会被调用,将数据放入队列中,并尝试合并数据。zip() 操作符会将多个 Observable 发射的数据按顺序一一对应地组合在一起,直到其中一个 Observable 完成发射。
接下来,我们看 combineLatest() 操作符的源码:
// Observable 类中的 combineLatest() 方法
public static <T1, T2, R> Observable<R> combineLatest(ObservableSource<? extends T1> source1,
ObservableSource<? extends T2> source2,
BiFunction<? super T1, ? super T2, ? extends R> combiner) {
// 检查传入的参数是否为 null
ObjectHelper.requireNonNull(source1, "source1 is null");
ObjectHelper.requireNonNull(source2, "source2 is null");
ObjectHelper.requireNonNull(combiner, "combiner is null");
// 创建一个 CombineLatestObservable 对象,并将两个 ObservableSource 和 combiner 函数作为参数传入
return RxJavaPlugins.onAssembly(new ObservableCombineLatest<T1, T2, R>(new ObservableSource[]{source1, source2}, combiner, false, bufferSize()));
}
// ObservableCombineLatest 类的定义
final class ObservableCombineLatest<T, R> extends Observable<R> {
// 存储多个 ObservableSource
final ObservableSource<? extends T>[] sources;
// 存储 combiner 函数
final Function<? super Object[], ? extends R> combiner;
// 存储是否延迟错误处理的标志
final boolean delayError;
// 存储缓冲区大小
final int bufferSize;
ObservableCombineLatest(ObservableSource<? extends T>[] sources,
Function<? super Object[], ? extends R> combiner,
boolean delayError, int bufferSize) {
// 初始化相关属性
this.sources = sources;
this.combiner = combiner;
this.delayError = delayError;
this.bufferSize = bufferSize;
}
@Override
protected void subscribeActual(Observer<? super R> t) {
// 创建一个 CombineLatestCoordinator 对象,并将原始的 observer、combiner 函数、delayError 和 bufferSize 作为参数传入
CombineLatestCoordinator<T, R> clc = new CombineLatestCoordinator<T, R>(t, combiner, sources.length, delayError, bufferSize);
clc.subscribe(sources);
}
// CombineLatestCoordinator 类的定义(部分代码)
static final class CombineLatestCoordinator<T, R> implements Disposable {
// 省略部分属性定义
CombineLatestCoordinator(Observer<? super R> actual,
Function<? super Object[], ? extends R> combiner,
int count, boolean delayError, int bufferSize) {
// 初始化相关属性
this.actual = actual;
this.combiner = combiner;
this.delayError = delayError;
this.bufferSize = bufferSize;
this.observers = new CombineLatestObserver[count];
this.values = new Object[count];
this.terminals = new AtomicInteger(count);
}
void subscribe(ObservableSource<? extends T>[] sources) {
CombineLatestObserver<T, R>[] s = observers;
int len = s.length;
for (int i = 0; i < len; i++) {
// 创建一个 CombineLatestObserver 对象,并将当前的 CombineLatestCoordinator 和索引作为参数传入
s[i] = new CombineLatestObserver<T, R>(this, i);
}
lazySet(0);
actual.onSubscribe(this);
for (int i = 0; i < len; i++) {
if (disposed) {
return;
}
// 将每个 CombineLatestObserver 订阅到对应的 ObservableSource 上
sources[i].subscribe(s[i]);
}
}
// 省略其他方法
}
// CombineLatestObserver 类的定义(部分代码)
static final class CombineLatestObserver<T, R> implements Observer<T> {
// 省略部分属性定义
CombineLatestObserver(CombineLatestCoordinator<T, R> parent, int index) {
// 初始化相关属性
this.parent = parent;
this.index = index;
this.queue = new SpscLinkedArrayQueue<T>(parent.bufferSize);
}
@Override
public void onNext(T t) {
// 将接收到的数据放入队列中
queue.offer(t);
// 尝试合并数据
parent.drain();
}
// 省略其他方法
}
}
在 combineLatest() 操作符中,创建了一个 ObservableCombineLatest 对象。在 subscribeActual() 方法中,创建了一个 CombineLatestCoordinator 对象,并调用其 subscribe() 方法,将每个 CombineLatestObserver 订阅到对应的 ObservableSource 上。当每个 ObservableSource 发射数据时,CombineLatestObserver 的 onNext() 方法会被调用,将数据放入队列中,并尝试合并数据。combineLatest() 操作符会在任何一个 Observable 发射新数据时,将所有 Observable 的最新数据组合在一起。
四、操作符组合的错误处理与重试机制
4.1 错误处理操作符组合
4.1.1 onErrorReturn() 和 onErrorResumeNext() 操作符组合
在 RxJava 中,onErrorReturn() 和 onErrorResumeNext() 是常用的错误处理操作符。onErrorReturn() 用于在发生错误时返回一个默认值,而 onErrorResumeNext() 用于在发生错误时切换到另一个 Observable 继续发射数据。
示例代码:
import io.reactivex.rxjava3.core.Observable;
public class ErrorHandlingExample {
public static void main(String[] args) {
// 创建一个 Observable,发射 1 到 3 的整数
Observable<Integer> source = Observable.just(1, 2, 3)
.map(item -> {
if (item == 2) {
// 模拟一个错误
throw new RuntimeException("Simulated error");
}
return item;
});
// 使用 onErrorReturn() 操作符处理错误
Observable<Integer> onErrorReturned = source.onErrorReturn(error -> -1);
// 使用 onErrorResumeNext() 操作符处理错误
Observable<Integer> onErrorResumed = source.onErrorResumeNext(Observable.just(4, 5));
// 订阅 onErrorReturn() 结果并打印
onErrorReturned.subscribe(System.out::println);
System.out.println("---");
// 订阅 onErrorResumeNext() 结果并打印
onErrorResumed.subscribe(System.out::println);
}
}
4.1.2 源码分析
首先,我们来看 onErrorReturn() 操作符的源码:
// Observable 类中的 onErrorReturn() 方法
public final Observable<T> onErrorReturn(Function<? super Throwable, ? extends T> valueSupplier) {
// 检查传入的 valueSupplier 函数是否为 null
ObjectHelper.requireNonNull(valueSupplier, "valueSupplier is null");
// 创建一个 OnErrorReturnObservable 对象,并将当前 Observable 和 valueSupplier 函数作为参数传入
return RxJavaPlugins.onAssembly(new OnErrorReturnObservable<T>(this, valueSupplier));
}
// OnErrorReturnObservable 类的定义
final class OnErrorReturnObservable<T> extends AbstractObservableWithUpstream<T, T> {
// 存储 valueSupplier 函数
final Function<? super Throwable, ? extends T> valueSupplier;
OnErrorReturnObservable(ObservableSource<T> source, Function<? super Throwable, ? extends T> valueSupplier) {
// 调用父类的构造函数,传入原始的 Observable
super(source);
// 初始化 valueSupplier 函数
this.valueSupplier = valueSupplier;
}
@Override
protected void subscribeActual(Observer<? super T> t) {
// 创建一个 OnErrorReturnObserver 对象,并将原始的 observer 和 valueSupplier 函数作为参数传入
source.subscribe(new OnErrorReturnObserver<T>(t, valueSupplier));
}
// OnErrorReturnObserver 类的定义
static final class OnErrorReturnObserver<T> extends BasicFuseableObserver<T, T> {
// 存储 valueSupplier 函数
final Function<? super Throwable, ? extends T> valueSupplier;
OnErrorReturnObserver(Observer<? super T> actual, Function<? super Throwable, ? extends T> valueSupplier) {
// 调用父类的构造函数,传入原始的 observer
super(actual);
// 初始化 valueSupplier 函数
this.valueSupplier = valueSupplier;
}
@Override
public void onError(Throwable t) {
T v;
try {
// 调用 valueSupplier 函数获取默认值
v = ObjectHelper.requireNonNull(valueSupplier.apply(t), "The valueSupplier returned a null value");
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
downstream.onError(new CompositeException(t, ex));
return;
}
// 将默认值传递给下游的 observer
downstream.onNext(v);
// 通知下游的 observer 完成
downstream.onComplete();
}
// 省略其他方法
}
}
在 onErrorReturn() 操作符中,创建了一个 OnErrorReturnObservable 对象。在 subscribeActual() 方法中,创建了一个 OnErrorReturnObserver 对象,并将其订阅到原始的 Observable 上。当原始的 Observable 发生错误时,OnErrorReturnObserver 的 onError() 方法会被调用,在该方法中,会调用 valueSupplier 函数获取默认值,并将其传递给下游的 observer,然后通知下游的 observer 完成。
接下来,我们看 onErrorResumeNext() 操作符的源码:
// Observable 类中的 onErrorResumeNext() 方法
public final Observable<T> onErrorResumeNext(ObservableSource<? extends T> next) {
// 检查传入的 next ObservableSource 是否为 null
ObjectHelper.requireNonNull(next, "next is null");
// 创建一个 OnErrorResumeNextObservable 对象,并将当前 Observable 和 next ObservableSource 作为参数传入
return RxJavaPlugins.onAssembly(new OnErrorResumeNextObservable<T>(this, next));
}
// OnErrorResumeNextObservable 类的定义
// OnErrorResumeNextObservable 类的定义
final class OnErrorResumeNextObservable<T> extends AbstractObservableWithUpstream<T, T> {
// 存储备用的 ObservableSource,当发生错误时将切换到该 ObservableSource 继续发射数据
final ObservableSource<? extends T> next;
OnErrorResumeNextObservable(ObservableSource<T> source, ObservableSource<? extends T> next) {
// 调用父类的构造函数,传入原始的 Observable
super(source);
// 初始化备用的 ObservableSource
this.next = next;
}
@Override
protected void subscribeActual(Observer<? super T> t) {
// 创建一个 OnErrorResumeNextObserver 对象,并将原始的 observer 和备用的 ObservableSource 作为参数传入
source.subscribe(new OnErrorResumeNextObserver<T>(t, next));
}
// OnErrorResumeNextObserver 类的定义
static final class OnErrorResumeNextObserver<T> extends AtomicInteger implements Observer<T>, Disposable {
// 存储下游的 observer
final Observer<? super T> downstream;
// 存储备用的 ObservableSource
final ObservableSource<? extends T> next;
// 存储当前的 Disposable 对象,用于取消订阅
Disposable upstream;
// 标记是否已经切换到备用的 ObservableSource
boolean inResume;
OnErrorResumeNextObserver(Observer<? super T> actual, ObservableSource<? extends T> next) {
// 初始化下游的 observer
this.downstream = actual;
// 初始化备用的 ObservableSource
this.next = next;
}
@Override
public void onSubscribe(Disposable d) {
// 如果已经切换到备用的 ObservableSource,则不处理该订阅事件
if (inResume) {
return;
}
// 存储当前的 Disposable 对象
upstream = d;
// 向下游的 observer 发送订阅事件
downstream.onSubscribe(this);
}
@Override
public void onNext(T t) {
// 向下游的 observer 发送数据
downstream.onNext(t);
}
@Override
public void onError(Throwable t) {
// 如果已经切换到备用的 ObservableSource,则直接将错误传递给下游的 observer
if (inResume) {
downstream.onError(t);
return;
}
// 标记为已经切换到备用的 ObservableSource
inResume = true;
// 取消当前的订阅
upstream.dispose();
// 订阅备用的 ObservableSource
next.subscribe(new InnerObserver());
}
@Override
public void onComplete() {
// 如果已经切换到备用的 ObservableSource,则直接将完成事件传递给下游的 observer
if (inResume) {
downstream.onComplete();
return;
}
// 向下游的 observer 发送完成事件
downstream.onComplete();
}
@Override
public void dispose() {
// 取消当前的订阅
upstream.dispose();
}
@Override
public boolean isDisposed() {
// 判断当前的订阅是否已经取消
return upstream.isDisposed();
}
// InnerObserver 类用于订阅备用的 ObservableSource
final class InnerObserver implements Observer<T> {
@Override
public void onSubscribe(Disposable d) {
// 存储备用 ObservableSource 的 Disposable 对象
upstream = d;
}
@Override
public void onNext(T t) {
// 向下游的 observer 发送数据
downstream.onNext(t);
}
@Override
public void onError(Throwable t) {
// 向下游的 observer 发送错误事件
downstream.onError(t);
}
@Override
public void onComplete() {
// 向下游的 observer 发送完成事件
downstream.onComplete();
}
}
}
}
在 onErrorResumeNext() 操作符中,创建了一个 OnErrorResumeNextObservable 对象。在 subscribeActual() 方法中,创建了一个 OnErrorResumeNextObserver 对象,并将其订阅到原始的 Observable 上。当原始的 Observable 发生错误时,OnErrorResumeNextObserver 的 onError() 方法会被调用,在该方法中,会取消当前的订阅,标记为已经切换到备用的 ObservableSource,并订阅备用的 ObservableSource。备用的 ObservableSource 发射的数据会通过 InnerObserver 传递给下游的 observer。
4.2 重试机制操作符组合
4.2.1 retry() 和 retryWhen() 操作符组合
retry() 操作符用于在发生错误时重试订阅,而 retryWhen() 操作符则提供了更灵活的重试策略,可以根据错误的类型和条件来决定是否重试。
示例代码:
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import java.util.concurrent.TimeUnit;
public class RetryExample {
public static void main(String[] args) {
// 创建一个 Observable,模拟可能会出错的操作
Observable<Integer> source = Observable.create(emitter -> {
System.out.println("Subscribing...");
// 模拟错误
emitter.onError(new RuntimeException("Simulated error"));
});
// 使用 retry() 操作符重试 3 次
Observable<Integer> retried = source.retry(3);
// 使用 retryWhen() 操作符,根据错误类型和条件进行重试
Observable<Integer> retriedWhen = source.retryWhen(errors ->
errors.zipWith(Observable.range(1, 3), (error, retryCount) -> retryCount)
.flatMap(retryCount -> {
System.out.println("Retrying attempt " + retryCount);
// 每次重试前等待 1 秒
return Observable.timer(1, TimeUnit.SECONDS);
})
);
// 订阅 retry() 结果并打印
retried.subscribe(
item -> System.out.println("Received: " + item),
error -> System.out.println("Error: " + error.getMessage())
);
try {
// 等待一段时间
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("---");
// 订阅 retryWhen() 结果并打印
retriedWhen.subscribe(
item -> System.out.println("Received: " + item),
error -> System.out.println("Error: " + error.getMessage())
);
try {
// 等待一段时间
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
4.2.2 源码分析
首先,我们来看 retry() 操作符的源码:
// Observable 类中的 retry() 方法
public final Observable<T> retry(long times) {
// 检查重试次数是否小于 0
if (times < 0) {
throw new IllegalArgumentException("times >= 0 required but it was " + times);
}
// 创建一个 ObservableRetry 对象,并将当前 Observable 和重试次数作为参数传入
return RxJavaPlugins.onAssembly(new ObservableRetry<T>(this, times));
}
// ObservableRetry 类的定义
final class ObservableRetry<T> extends AbstractObservableWithUpstream<T, T> {
// 存储重试次数
final long times;
ObservableRetry(ObservableSource<T> source, long times) {
// 调用父类的构造函数,传入原始的 Observable
super(source);
// 初始化重试次数
this.times = times;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
// 创建一个 RetryObserver 对象,并将原始的 observer、当前 Observable 和重试次数作为参数传入
RetryObserver<T> parent = new RetryObserver<T>(observer, times, this.source);
// 开始订阅
parent.subscribeNext();
}
// RetryObserver 类的定义
static final class RetryObserver<T> extends AtomicInteger implements Observer<T> {
// 存储下游的 observer
final Observer<? super T> downstream;
// 存储剩余的重试次数
long remaining;
// 存储原始的 ObservableSource
final ObservableSource<T> source;
// 存储当前的 Disposable 对象,用于取消订阅
Disposable upstream;
RetryObserver(Observer<? super T> actual, long times, ObservableSource<T> source) {
// 初始化下游的 observer
this.downstream = actual;
// 初始化剩余的重试次数
this.remaining = times;
// 初始化原始的 ObservableSource
this.source = source;
}
void subscribeNext() {
// 检查是否还有剩余的重试次数
if (getAndIncrement() == 0) {
while (true) {
if (upstream != null) {
// 取消当前的订阅
upstream.dispose();
}
// 订阅原始的 ObservableSource
source.subscribe(this);
if (decrementAndGet() == 0) {
break;
}
}
}
}
@Override
public void onSubscribe(Disposable d) {
// 存储当前的 Disposable 对象
upstream = d;
// 向下游的 observer 发送订阅事件
downstream.onSubscribe(this);
}
@Override
public void onNext(T t) {
// 向下游的 observer 发送数据
downstream.onNext(t);
}
@Override
public void onError(Throwable t) {
// 检查是否还有剩余的重试次数
if (remaining-- > 0) {
// 进行重试
subscribeNext();
} else {
// 没有剩余的重试次数,将错误传递给下游的 observer
downstream.onError(t);
}
}
@Override
public void onComplete() {
// 向下游的 observer 发送完成事件
downstream.onComplete();
}
}
}
在 retry() 操作符中,创建了一个 ObservableRetry 对象。在 subscribeActual() 方法中,创建了一个 RetryObserver 对象,并调用其 subscribeNext() 方法开始订阅。当发生错误时,RetryObserver 的 onError() 方法会被调用,在该方法中,会检查是否还有剩余的重试次数,如果有,则调用 subscribeNext() 方法进行重试;如果没有,则将错误传递给下游的 observer。
接下来,我们看 retryWhen() 操作符的源码:
// Observable 类中的 retryWhen() 方法
public final Observable<T> retryWhen(Function<? super Observable<Throwable>, ? extends ObservableSource<?>> handler) {
// 检查传入的 handler 函数是否为 null
ObjectHelper.requireNonNull(handler, "handler is null");
// 创建一个 ObservableRetryWhen 对象,并将当前 Observable 和 handler 函数作为参数传入
return RxJavaPlugins.onAssembly(new ObservableRetryWhen<T>(this, handler));
}
// ObservableRetryWhen 类的定义
final class ObservableRetryWhen<T> extends AbstractObservableWithUpstream<T, T> {
// 存储处理重试逻辑的 handler 函数
final Function<? super Observable<Throwable>, ? extends ObservableSource<?>> handler;
ObservableRetryWhen(ObservableSource<T> source, Function<? super Observable<Throwable>, ? extends ObservableSource<?>> handler) {
// 调用父类的构造函数,传入原始的 Observable
super(source);
// 初始化处理重试逻辑的 handler 函数
this.handler = handler;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
// 创建一个 PublishSubject 对象,用于发送错误事件
PublishSubject<Throwable> errorHandler = PublishSubject.create();
ObservableSource<?> decision;
try {
// 调用 handler 函数,根据错误事件生成一个新的 ObservableSource
decision = ObjectHelper.requireNonNull(handler.apply(errorHandler), "The handler returned a null ObservableSource");
} catch (Throwable t) {
// 处理异常,将异常传递给下游的 observer
Exceptions.throwIfFatal(t);
EmptyDisposable.error(t, observer);
return;
}
// 创建一个 RetryWhenObserver 对象,并将原始的 observer、当前 Observable、errorHandler 和 decision 作为参数传入
RetryWhenObserver<T> parent = new RetryWhenObserver<T>(observer, source, errorHandler, decision);
// 开始订阅 decision ObservableSource
decision.subscribe(parent);
// 开始订阅原始的 ObservableSource
parent.subscribeNext();
}
// RetryWhenObserver 类的定义
static final class RetryWhenObserver<T> extends AtomicInteger implements Observer<Object>, Disposable {
// 存储下游的 observer
final Observer<? super T> downstream;
// 存储原始的 ObservableSource
final ObservableSource<T> source;
// 存储用于发送错误事件的 PublishSubject
final PublishSubject<Throwable> errorHandler;
// 存储当前的 Disposable 对象,用于取消订阅
Disposable upstream;
// 存储 decision ObservableSource 的 Disposable 对象
Disposable decision;
// 标记是否已经完成
boolean done;
RetryWhenObserver(Observer<? super T> actual, ObservableSource<T> source,
PublishSubject<Throwable> errorHandler, ObservableSource<?> decision) {
// 初始化下游的 observer
this.downstream = actual;
// 初始化原始的 ObservableSource
this.source = source;
// 初始化用于发送错误事件的 PublishSubject
this.errorHandler = errorHandler;
}
void subscribeNext() {
// 检查是否已经完成
if (!done) {
// 检查是否正在处理中
if (getAndIncrement() == 0) {
while (true) {
if (done) {
return;
}
// 取消当前的订阅
if (upstream != null) {
upstream.dispose();
}
// 订阅原始的 ObservableSource
source.subscribe(new InnerObserver());
if (decrementAndGet() == 0) {
break;
}
}
}
}
}
@Override
public void onSubscribe(Disposable d) {
// 存储 decision ObservableSource 的 Disposable 对象
decision = d;
// 向下游的 observer 发送订阅事件
downstream.onSubscribe(this);
}
@Override
public void onNext(Object t) {
// 进行重试
subscribeNext();
}
@Override
public void onError(Throwable t) {
// 标记为已经完成
done = true;
// 取消当前的订阅
if (upstream != null) {
upstream.dispose();
}
// 将错误传递给下游的 observer
downstream.onError(t);
}
@Override
public void onComplete() {
// 标记为已经完成
done = true;
// 取消当前的订阅
if (upstream != null) {
upstream.dispose();
}
// 向下游的 observer 发送完成事件
downstream.onComplete();
}
@Override
public void dispose() {
// 取消当前的订阅
upstream.dispose();
// 取消 decision ObservableSource 的订阅
decision.dispose();
}
@Override
public boolean isDisposed() {
// 判断当前的订阅是否已经取消
return decision.isDisposed();
}
// InnerObserver 类用于订阅原始的 ObservableSource
final class InnerObserver implements Observer<T> {
@Override
public void onSubscribe(Disposable d) {
// 存储当前的 Disposable 对象
upstream = d;
}
@Override
public void onNext(T t) {
// 向下游的 observer 发送数据
downstream.onNext(t);
}
@Override
public void onError(Throwable t) {
// 将错误发送到 errorHandler 中
errorHandler.onNext(t);
}
@Override
public void onComplete() {
// 标记为已经完成
done = true;
// 取消 decision ObservableSource 的订阅
decision.dispose();
// 向下游的 observer 发送完成事件
downstream.onComplete();
}
}
}
}
在 retryWhen() 操作符中,创建了一个 ObservableRetryWhen 对象。在 subscribeActual() 方法中,创建了一个 PublishSubject 对象用于发送错误事件,调用 handler 函数根据错误事件生成一个新的 ObservableSource(即 decision)。然后创建一个 RetryWhenObserver 对象,先订阅 decision,再订阅原始的 ObservableSource。当原始的 ObservableSource 发生错误时,InnerObserver 的 onError() 方法会将错误发送到 errorHandler 中,decision 会根据这些错误事件决定是否进行重试。如果 decision 发射了新的数据,RetryWhenObserver 的 onNext() 方法会被调用,进行重试操作。
五、操作符组合的线程调度
5.1 subscribeOn() 和 observeOn() 操作符组合
5.1.1 示例代码
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;
public class ThreadSchedulingExample {
public static void main(String[] args) {
// 创建一个 Observable,发射 1 到 3 的整数
Observable<Integer> source = Observable.just(1, 2, 3)
.subscribeOn(Schedulers.io()) // 指定订阅操作在 IO 线程中执行
.map(item -> {
System.out.println("Mapping on thread: " + Thread.currentThread().getName());
return item * 2;
})
.observeOn(Schedulers.computation()) // 指定观察操作在计算线程中执行
.filter(item -> {
System.out.println("Filtering on thread: " + Thread.currentThread().getName());
return item > 2;
});
// 订阅并打印结果
source.subscribe(item -> {
System.out.println("Received on thread: " + Thread.currentThread().getName() + ", item: " + item);
});
try {
// 等待一段时间,确保所有操作完成
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
5.1.2 源码分析
首先,我们来看 subscribeOn() 操作符的源码:
// Observable 类中的 subscribeOn() 方法
public final Observable<T> subscribeOn(Scheduler scheduler) {
// 检查传入的 scheduler 是否为 null
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
// 创建一个 ObservableSubscribeOn 对象,并将当前 Observable 和 scheduler 作为参数传入
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}
// ObservableSubscribeOn 类的定义
final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
// 存储调度器
final Scheduler scheduler;
ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
// 调用父类的构造函数,传入原始的 Observable
super(source);
// 初始化调度器
this.scheduler = scheduler;
}
@Override
protected void subscribeActual(final Observer<? super T> observer) {
// 创建一个 SubscribeOnObserver 对象,并将原始的 observer 作为参数传入
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(observer);
// 向下游的 observer 发送订阅事件
observer.onSubscribe(parent);
// 在调度器指定的线程中执行订阅操作
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}
// SubscribeOnObserver 类的定义
static final class SubscribeOnObserver<T> extends AtomicReference<Disposable> implements Observer<T>, Disposable {
// 存储下游的 observer
final Observer<? super T> downstream;
// 存储当前的 Disposable 对象,用于取消订阅
final AtomicReference<Disposable> upstream;
SubscribeOnObserver(Observer<? super T> actual) {
// 初始化下游的 observer
this.downstream = actual;
// 初始化存储 Disposable 对象的 AtomicReference
this.upstream = new AtomicReference<Disposable>();
}
@Override
public void onSubscribe(Disposable d) {
// 设置上游的 Disposable 对象
DisposableHelper.setOnce(this.upstream, d);
}
@Override
public void onNext(T t) {
// 向下游的 observer 发送数据
downstream.onNext(t);
}
@Override
public void onError(Throwable t) {
// 向下游的 observer 发送错误事件
downstream.onError(t);
}
@Override
public void onComplete() {
// 向下游的 observer 发送完成事件
downstream.onComplete();
}
@Override
public void dispose() {
// 取消上游的订阅
DisposableHelper.dispose(upstream);
// 取消当前的订阅
DisposableHelper.dispose(this);
}
@Override
public boolean isDisposed() {
// 判断当前的订阅是否已经取消
return DisposableHelper.isDisposed(get());
}
void setDisposable(Disposable d) {
// 设置当前的 Disposable 对象
DisposableHelper.setOnce(this, d);
}
}
// SubscribeTask 类用于在调度器指定的线程中执行订阅操作
final class SubscribeTask implements Runnable {
// 存储 SubscribeOnObserver 对象
private final SubscribeOnObserver<T> parent;
SubscribeTask(SubscribeOnObserver<T> parent) {
// 初始化 SubscribeOnObserver 对象
this.parent = parent;
}
@Override
public void run() {
// 在调度器指定的线程中订阅原始的 ObservableSource
source.subscribe(parent);
}
}
}
在 subscribeOn() 操作符中,创建了一个 ObservableSubscribeOn 对象。在 subscribeActual() 方法中,创建了一个 SubscribeOnObserver 对象,并向下游的 observer 发送订阅事件。然后,使用调度器的 scheduleDirect() 方法在指定的线程中执行 SubscribeTask,SubscribeTask 的 run() 方法会在指定的线程中订阅原始的 ObservableSource。
接下来,我们看 observeOn() 操作符的源码:
// Observable 类中的 observeOn() 方法
public final Observable<T> observeOn(Scheduler scheduler) {
// 调用重载的 observeOn() 方法,传入调度器和默认参数
return observeOn(scheduler, false, bufferSize());
}
// Observable 类中的重载 observeOn() 方法
public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
// 检查传入的调度器是否为 null
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
// 检查缓冲区大小是否小于 1
ObjectHelper.verifyPositive(bufferSize, "bufferSize");
// 创建一个 ObservableObserveOn 对象,并将当前 Observable、调度器、是否延迟错误处理和缓冲区大小作为参数传入
return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
}
// ObservableObserveOn 类的定义
final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> {
// 存储调度器
final Scheduler scheduler;
// 存储是否延迟错误处理的标志
final boolean delayError;
// 存储缓冲区大小
final int bufferSize;
ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean delayError, int bufferSize) {
// 调用父类的构造函数,传入原始的 Observable
super(source);
// 初始化调度器
this.scheduler = scheduler;
// 初始化是否延迟错误处理的标志
this.delayError = delayError;
// 初始化缓冲区大小
this.bufferSize = bufferSize;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
// 检查调度器是否为 TrampolineScheduler
if (scheduler instanceof TrampolineScheduler) {
// 如果是 TrampolineScheduler,则直接订阅原始的 ObservableSource
source.subscribe(observer);
} else {
// 创建一个 ObserveOnObserver 对象,并将原始的 observer、调度器、是否延迟错误处理和缓冲区大小作为参数传入
Scheduler.Worker w = scheduler.createWorker();
source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
}
}
// ObserveOnObserver 类的定义
static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T> implements Observer<T>, Runnable {
// 存储下游的 observer
final Observer<? super T> downstream;
// 存储调度器的工作者
final Scheduler.Worker worker;
// 存储是否延迟错误处理的标志
final boolean delayError;
// 存储缓冲区大小
final int bufferSize;
// 存储上游的 Disposable 对象
Disposable upstream;
// 存储队列
SimpleQueue<T> queue;
// 标记是否已经完成
volatile boolean done;
// 标记是否已经取消
volatile boolean disposed;
// 存储错误信息
Throwable error;
// 标记是否已经调度
boolean outputFused;
ObserveOnObserver(Observer<? super T> actual, Scheduler.Worker worker, boolean delayError, int bufferSize) {
// 初始化下游的 observer
this.downstream = actual;
// 初始化调度器的工作者
this.worker = worker;
// 初始化是否延迟错误处理的标志
this.delayError = delayError;
// 初始化缓冲区大小
this.bufferSize = bufferSize;
}
@Override
public void onSubscribe(Disposable d) {
// 检查是否已经取消
if (DisposableHelper.validate(this.upstream, d)) {
// 设置上游的 Disposable 对象
this.upstream = d;
if (d instanceof QueueDisposable) {
QueueDisposable<T> qd = (QueueDisposable<T>) d;
int m = qd.requestFusion(QueueDisposable.ANY | QueueDisposable.BOUNDARY);
if (m == QueueDisposable.SYNC) {
// 同步融合模式
outputFused = true;
queue = qd;
done = true;
downstream.onSubscribe(this);
schedule();
return;
}
if (m == QueueDisposable.ASYNC) {
// 异步融合模式
outputFused = true;
queue = qd;
downstream.onSubscribe(this);
return;
}
}
// 创建一个队列
queue = new SpscLinkedArrayQueue<T>(bufferSize);
// 向下游的 observer 发送订阅事件
downstream.onSubscribe(this);
}
}
@Override
public void onNext(T t) {
// 如果已经完成或取消,则直接返回
if (done || disposed) {
return;
}
if (outputFused) {
// 如果是融合模式,直接调用下游的 onNext() 方法
downstream.onNext(null);
return;
}
// 将数据放入队列中
if (!queue.offer(t)) {
// 如果队列已满,取消订阅并发送错误事件
upstream.dispose();
error = new IllegalStateException("Queue is full?!");
done = true;
}
// 调度任务
schedule();
}
@Override
public void onError(Throwable t) {
// 如果已经完成或取消,则直接返回
if (done || disposed) {
RxJavaPlugins.onError(t);
return;
}
// 存储错误信息
error = t;
done = true;
// 调度任务
schedule();
}
@Override
public void onComplete() {
// 如果已经完成或取消,则直接返回
if (done || disposed) {
return;
}
// 标记为已经完成
done = true;
// 调度任务
schedule();
}
@Override
public void dispose() {
// 如果还未取消
if (!disposed) {
// 标记为已经取消
disposed = true;
// 取消上游的订阅
upstream.dispose();
// 取消调度器的工作者
worker.dispose();
if (getAndIncrement() == 0) {
// 清空队列
queue.clear();
}
}
}
@Override
public boolean isDisposed() {
// 判断是否已经取消
return disposed;
}
void schedule() {
// 如果当前任务没有正在执行
if (getAndIncrement() == 0) {
// 调度当前任务在调度器的线程中执行
worker.schedule(this);
}
}
@Override
public void run() {
// 如果是融合模式
if (outputFused) {
// 执行融合模式的操作
drainFused();
} else {
// 执行非融合模式的操作
drainNormal();
}
}
void drainNormal() {
// 存储队列中的元素数量
int missed = 1;
// 获取队列
final SimpleQueue<T> q = queue;
// 获取下游的 observer
final Observer<? super T> a = downstream;
while (true) {
// 如果已经取消,则清空队列并返回
if (checkTerminated(done, q.isEmpty(), a)) {
return;
}
while (true) {
// 标记是否完成
boolean d = done;
// 从队列中取出元素
T v;
try {
v = q.poll();
} catch (Throwable ex) {
// 处理异常
Exceptions.throwIfFatal(ex);
upstream.dispose();
q.clear();
a.onError(ex);
worker.dispose();
return;
}
// 判断元素是否为空
boolean empty = v == null;
// 如果已经完成且队列为空,则通知下游完成
if (checkTerminated(d, empty, a)) {
return;
}
// 如果队列为空,则跳出循环
if (empty) {
break;
}
// 向下游的 observer 发送元素
a.onNext(v);
}
// 更新当前任务的执行状态
missed = addAndGet(-missed);
// 如果没有其他任务需要执行,则跳出循环
if (missed == 0) {
break;
}
}
}
void drainFused() {
// 存储队列中的元素数量
int missed = 1;
// 获取下游的 observer
final Observer<? super T> a = downstream;
while (true) {
// 如果已经取消,则返回
if (disposed) {
return;
}
// 标记是否完成
boolean d = done;
// 获取错误信息
Throwable err = error;
// 如果完成且有错误信息,则通知下游错误
if (d && !delayError && err != null) {
a.onError(err);
worker.dispose();
return;
}
// 向下游的 observer 发送元素
a.onNext(null);
// 如果完成,则通知下游完成
if (d) {
if (err != null) {
a.onError(err);
} else {
a.onComplete();
}
worker.dispose();
return;
}
// 更新当前任务的执行状态
missed = addAndGet(-missed);
// 如果没有其他任务需要执行,则跳出循环
if (missed == 0) {
break;
}
}
}
boolean checkTerminated(boolean d, boolean empty, Observer<? super T> a) {
// 如果已经取消,则清空队列并返回 true
if (disposed) {
queue.clear();
return true;
}
// 如果完成
if (d) {
// 获取错误信息
Throwable e = error;
// 如果延迟错误处理且有错误信息,则通知下游错误
if (delayError) {
if (empty) {
if (e != null) {
a.onError(e);
} else {
a.onComplete();
}
worker.dispose();
return true;
}
} else {
// 如果不延迟错误处理且有错误信息,则通知下游错误
if (e != null) {
queue.clear();
a.onError(e);
worker.dispose();
return true;
} else if (empty) {
// 如果没有错误信息且队列为空,则通知下游完成
a.onComplete();
worker.dispose();
return true;
}
}
}
// 否则返回 false
return false;
}
@Override
public int requestFusion(int mode) {
// 如果支持同步融合模式
if ((mode & ASYNC) != 0) {
outputFused = true;
return ASYNC;
}
// 否则返回 0
return 0;
}
@Override
public T poll() throws Exception {
// 从队列中取出元素
return queue.poll();
}
@Override
public boolean isEmpty() {
// 判断队列是否为空
return queue.isEmpty();
}
@Override
public void clear() {
// 清空队列
queue.clear();
}
}
}
在 observeOn() 操作符中,创建了一个 ObservableObserveOn 对象。在 subscribeActual() 方法中,如果调度器是 TrampolineScheduler,则直接订阅原始的 ObservableSource;否则,创建一个 ObserveOnObserver 对象,并将其订阅到原始的 ObservableSource 上。ObserveOnObserver 会将接收到的数据放入队列中,并通过调度器在指定的线程中调度任务,将队列中的数据传递给下游的 observer。
5.2 线程调度的注意事项
5.2.1 subscribeOn() 的多次调用
在 RxJava 中,subscribeOn() 操作符用于指定 Observable 发射数据的线程。值得注意的是,多次调用 subscribeOn() 时,只有第一次调用会生效。这是因为一旦订阅操作在某个线程上被调度,后续的 subscribeOn() 调用无法改变这个已经确定的订阅线程。
示例代码如下:
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;
public class MultipleSubscribeOnExample {
public static void main(String[] args) {
Observable.just(1, 2, 3)
.subscribeOn(Schedulers.io())
.subscribeOn(Schedulers.computation())
.map(item -> {
System.out.println("Mapping on thread: " + Thread.currentThread().getName());
return item * 2;
})
.subscribe(item -> {
System.out.println("Received on thread: " + Thread.currentThread().getName() + ", item: " + item);
});
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在上述代码中,虽然先后调用了 subscribeOn(Schedulers.io()) 和 subscribeOn(Schedulers.computation()),但实际上订阅操作只会在第一次指定的 Schedulers.io() 线程上执行。
从源码角度分析,subscribeOn() 操作符会创建 ObservableSubscribeOn 对象。在 subscribeActual() 方法中,会使用指定的调度器调度 SubscribeTask 来执行订阅操作。一旦这个调度过程确定,后续再次调用 subscribeOn() 创建的新 ObservableSubscribeOn 对象无法改变已经开始的调度。
5.2.2 observeOn() 的多次调用
与 subscribeOn() 不同,多次调用 observeOn() 是有效的,每次调用都会改变后续操作符和观察者执行的线程。这是因为 observeOn() 操作符会将接收到的数据放入队列中,并在指定的线程中调度任务,将队列中的数据传递给下游。
示例代码如下:
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;
public class MultipleObserveOnExample {
public static void main(String[] args) {
Observable.just(1, 2, 3)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.computation())
.map(item -> {
System.out.println("First mapping on thread: " + Thread.currentThread().getName());
return item * 2;
})
.observeOn(Schedulers.newThread())
.map(item -> {
System.out.println("Second mapping on thread: " + Thread.currentThread().getName());
return item + 1;
})
.subscribe(item -> {
System.out.println("Received on thread: " + Thread.currentThread().getName() + ", item: " + item);
});
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在这个例子中,第一个 observeOn(Schedulers.computation()) 使得第一个 map() 操作符在计算线程中执行,第二个 observeOn(Schedulers.newThread()) 则让第二个 map() 操作符和最终的 subscribe() 在新线程中执行。
从源码来看,每次调用 observeOn() 都会创建一个 ObservableObserveOn 对象。在 subscribeActual() 方法中,会创建 ObserveOnObserver 对象。每个 ObserveOnObserver 都会根据其对应的调度器,在指定线程中调度任务,从而实现对后续操作符和观察者线程的改变。
5.2.3 线程安全问题
在使用 RxJava 进行线程调度时,必须要考虑线程安全问题。当多个线程同时访问和修改共享资源时,可能会出现数据不一致或其他并发问题。
例如,在下面的代码中,多个线程可能会同时修改 sharedCounter 变量:
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;
public class ThreadSafetyExample {
private static int sharedCounter = 0;
public static void main(String[] args) {
Observable.range(1, 100)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.computation())
.subscribe(item -> {
// 多个线程可能同时修改 sharedCounter
sharedCounter++;
System.out.println("Counter: " + sharedCounter);
});
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
为了解决这个问题,可以使用线程安全的数据结构(如 AtomicInteger)或同步机制(如 synchronized 关键字)。修改后的代码如下:
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadSafetyFixedExample {
private static AtomicInteger sharedCounter = new AtomicInteger(0);
public static void main(String[] args) {
Observable.range(1, 100)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.computation())
.subscribe(item -> {
// 使用 AtomicInteger 保证线程安全
int value = sharedCounter.incrementAndGet();
System.out.println("Counter: " + value);
});
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在修改后的代码中,使用 AtomicInteger 替代了普通的 int 变量,AtomicInteger 提供了原子操作方法,确保在多线程环境下对计数器的操作是线程安全的。
5.2.4 资源管理问题
线程调度可能会引入资源管理问题。例如,在 Schedulers.io() 中创建的线程池用于处理 I/O 密集型任务,如果在使用过程中没有正确管理这些线程资源,可能会导致资源耗尽。
另外,当使用自定义调度器时,需要确保在不需要时正确关闭调度器,释放相关资源。例如,使用 ExecutorService 作为自定义调度器时,需要在适当的时候调用 shutdown() 方法:
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CustomSchedulerResourceManagementExample {
public static void main(String[] args) {
// 创建自定义线程池
ExecutorService executorService = Executors.newFixedThreadPool(2);
Observable.just(1, 2, 3)
.subscribeOn(Schedulers.from(executorService))
.subscribe(item -> {
System.out.println("Received on custom thread: " + Thread.currentThread().getName() + ", item: " + item);
});
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 关闭线程池,释放资源
executorService.shutdown();
}
}
在这个例子中,创建了一个固定大小的线程池作为自定义调度器。在完成任务后,调用 executorService.shutdown() 方法关闭线程池,避免资源泄漏。
六、操作符组合的性能优化
6.1 减少不必要的操作符
在使用 RxJava 操作符组合时,应尽量减少不必要的操作符。每一个操作符都会引入一定的开销,包括创建新的 Observable、Observer 以及数据处理的逻辑。过多的操作符会增加内存使用和处理时间,降低性能。
例如,下面的代码中存在不必要的操作符:
import io.reactivex.rxjava3.core.Observable;
public class UnnecessaryOperatorsExample {
public static void main(String[] args) {
Observable.just(1, 2, 3)
.map(item -> item) // 不必要的 map 操作
.filter(item -> true) // 不必要的 filter 操作
.subscribe(System.out::println);
}
}
在这个例子中,map(item -> item) 并没有对数据进行实际的转换,filter(item -> true) 也没有过滤掉任何数据,这些操作符是多余的,可以直接去掉:
import io.reactivex.rxjava3.core.Observable;
public class OptimizedOperatorsExample {
public static void main(String[] args) {
Observable.just(1, 2, 3)
.subscribe(System.out::println);
}
}
从源码角度来看,每个操作符都会创建新的 Observable 子类对象,如 ObservableMap、ObservableFilter 等。这些对象的创建和管理会消耗一定的内存和 CPU 资源。减少不必要的操作符可以避免这些额外的开销。
6.2 合理使用背压策略
背压是指在异步场景下,当上游 Observable 发射数据的速度快于下游 Observer 处理数据的速度时,需要采取的一种策略来处理这种数据积压问题。RxJava 提供了多种背压策略,如 BUFFER、DROP、LATEST 等,合理选择背压策略可以有效避免内存溢出和性能问题。
6.2.1 BUFFER 策略
BUFFER 策略会将上游发射的数据存储在一个缓冲区中,直到下游 Observer 有能力处理这些数据。这种策略适用于下游 Observer 偶尔处理速度较慢,但最终能够处理所有数据的情况。
示例代码如下:
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import java.util.concurrent.TimeUnit;
public class BufferBackpressureExample {
public static void main(String[] args) {
Flowable.interval(1, TimeUnit.MILLISECONDS)
.onBackpressureBuffer()
.observeOn(Schedulers.single())
.subscribe(item -> {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Received: " + item);
});
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在这个例子中,上游的 Flowable.interval(1, TimeUnit.MILLISECONDS) 每秒发射 1000 个数据,而下游的 Observer 每 100 毫秒处理一个数据。使用 onBackpressureBuffer() 策略,会将未处理的数据存储在缓冲区中,等待下游处理。
6.2.2 DROP 策略
DROP 策略会在缓冲区满时丢弃新的数据。这种策略适用于对数据实时性要求较高,且允许部分数据丢失的场景。
示例代码如下:
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import java.util.concurrent.TimeUnit;
public class DropBackpressureExample {
public static void main(String[] args) {
Flowable.interval(1, TimeUnit.MILLISECONDS)
.onBackpressureDrop()
.observeOn(Schedulers.single())
.subscribe(item -> {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Received: " + item);
});
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在这个例子中,当缓冲区满时,新发射的数据会被丢弃,以保证系统的性能和稳定性。
6.2.3 LATEST 策略
LATEST 策略会在缓冲区满时,只保留最新的数据,丢弃旧的数据。这种策略适用于只关心最新数据的场景。
示例代码如下:
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import java.util.concurrent.TimeUnit;
public class LatestBackpressureExample {
public static void main(String[] args) {
Flowable.interval(1, TimeUnit.MILLISECONDS)
.onBackpressureLatest()
.observeOn(Schedulers.single())
.subscribe(item -> {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Received: " + item);
});
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
从源码角度来看,不同的背压策略在 Flowable 的实现中通过不同的操作符来处理数据。例如,onBackpressureBuffer() 会创建一个 FlowableOnBackpressureBuffer 对象,在内部维护一个缓冲区来存储数据;onBackpressureDrop() 会创建一个 FlowableOnBackpressureDrop 对象,在缓冲区满时丢弃新的数据;onBackpressureLatest() 会创建一个 FlowableOnBackpressureLatest 对象,只保留最新的数据。
6.3 避免嵌套 Observable
嵌套 Observable 会增加代码的复杂度和性能开销。当一个 Observable 内部又创建了另一个 Observable 时,会导致嵌套的订阅和数据处理逻辑,增加内存使用和处理时间。
例如,下面的代码存在嵌套 Observable:
import io.reactivex.rxjava3.core.Observable;
public class NestedObservableExample {
public static void main(String[] args) {
Observable.just(1, 2, 3)
.flatMap(item ->
Observable.just(item * 2)
)
.subscribe(System.out::println);
}
}
在这个例子中,flatMap() 操作符内部又创建了一个新的 Observable。可以通过优化,避免这种嵌套:
import io.reactivex.rxjava3.core.Observable;
public class OptimizedNestedObservableExample {
public static void main(String[] args) {
Observable.just(1, 2, 3)
.map(item -> item * 2)
.subscribe(System.out::println);
}
}
从源码角度来看,嵌套 Observable 会创建多个 Observable 子类对象和 Observer 对象,增加了对象的创建和管理开销。避免嵌套 Observable 可以减少这些不必要的开销,提高性能。
6.4 及时取消订阅
在使用 RxJava 时,及时取消订阅可以避免内存泄漏和不必要的资源消耗。当一个 Observable 不再需要时,如果没有及时取消订阅,它可能会继续发射数据,占用系统资源。
例如,下面的代码在订阅后没有及时取消:
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.Disposable;
import java.util.concurrent.TimeUnit;
public class UncancelledSubscriptionExample {
public static void main(String[] args) {
Observable.interval(1, TimeUnit.SECONDS)
.subscribe(item -> {
System.out.println("Received: " + item);
});
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
可以通过保存 Disposable 对象,并在需要时调用 dispose() 方法来取消订阅:
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.Disposable;
import java.util.concurrent.TimeUnit;
public class CancelledSubscriptionExample {
public static void main(String[] args) {
Disposable disposable = Observable.interval(1, TimeUnit.SECONDS)
.subscribe(item -> {
System.out.println("Received: " + item);
});
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 取消订阅
disposable.dispose();
}
}
从源码角度来看,Disposable 接口定义了 dispose() 方法,用于取消订阅。当调用 dispose() 方法时,会通知 Observable 停止发射数据,并释放相关资源。
七、总结与展望
7.1 总结
RxJava 的操作符组合模块为开发者提供了强大而灵活的工具,用于处理异步事件流。通过对常见操作符组合(如 map() 和 filter()、flatMap() 和 concatMap()、zip() 和 combineLatest() 等)的分析,我们深入了解了它们的使用原理和源码实现。
操作符组合可以将复杂的数据流处理逻辑分解为多个简单的步骤,提高代码的可读性和可维护性。同时,通过错误处理和重试机制(如 onErrorReturn()、onErrorResumeNext()、retry() 和 retryWhen()),可以增强系统的健壮性。线程调度操作符(subscribeOn() 和 observeOn())则允许开发者灵活控制数据发射和处理的线程,提高系统的性能和响应能力。
然而,在使用操作符组合时,也需要注意一些问题。例如,要避免不必要的操作符,合理使用背压策略,避免嵌套 Observable,以及及时取消订阅,以提高性能和避免资源泄漏。
7.2 展望
随着软件开发的不断发展,响应式编程的应用场景将会越来越广泛。RxJava 作为 Java 平台上优秀的响应式编程库,其操作符组合模块也有望得到进一步的发展和完善。
未来,可能会有更多功能强大的操作符被添加到 RxJava 中,以满足不同场景下的需求。例如,更复杂的数据流合并和拆分操作符,以及更智能的错误处理和重试策略。
同时,RxJava 可能会更好地与其他技术和框架集成,如 Android 开发、微服务架构等。在 Android 开发中,RxJava 可以与 Android 的生命周期管理更好地结合,减少内存泄漏和性能问题。在微服务架构中,RxJava 可以用于处理异步的网络请求和事件流,提高系统的并发处理能力。
另外,随着 Java 语言本身的发展,RxJava 也可能会进行相应的优化和改进,以充分利用 Java 的新特性,提高代码的简洁性和性能。
总之,RxJava 的操作符组合模块具有广阔的发展前景,开发者可以通过深入学习和掌握这些操作符,更好地应对各种复杂的异步编程场景。