1. 组合操作符实现原理
1.1 zip() 操作符源码解析
public static <T, R> Observable<R> zip(
Iterable<? extends ObservableSource<? extends T>> sources,
Function<? super Object[], ? extends R> zipper) {
return new ObservableZip<>(null, sources, zipper, bufferSize(), false);
}
ObservableZip 核心结构:
public final class ObservableZip<T, R> extends Observable<R> {
final ObservableSource<? extends T>[] sources;
final Function<? super Object[], ? extends R> zipper;
final int bufferSize;
final boolean delayError;
@Override
public void subscribeActual(Observer<? super R> observer) {
// 创建ZipCoordinator
ZipCoordinator<T, R> zc = new ZipCoordinator<>(observer, zipper, sources.length, bufferSize, delayError);
// 订阅所有源
zc.subscribe(sources, bufferSize);
}
}
ZipCoordinator 关键实现:
static final class ZipCoordinator<T, R> extends AtomicInteger
implements Disposable {
final Observer<? super R> downstream;
final Function<? super Object[], ? extends R> zipper;
final ZipObserver<T, R>[] observers;
final Object[] values;
ZipCoordinator(Observer<? super R> actual,
Function<? super Object[], ? extends R> zipper,
int count, int bufferSize, boolean delayError) {
this.downstream = actual;
this.zipper = zipper;
this.observers = new ZipObserver[count];
this.values = new Object[count];
for (int i = 0; i < count; i++) {
observers[i] = new ZipObserver<>(this, bufferSize, delayError);
}
}
void subscribe(ObservableSource<? extends T>[] sources, int bufferSize) {
for (int i = 0; i < observers.length; i++) {
// 订阅每个源
sources[i].subscribe(observers[i]);
}
}
void drain() {
if (getAndIncrement() != 0) return;
int missing = 1;
for (;;) {
boolean allHaveValues = true;
// 检查所有源是否都有数据
for (int i = 0; i < observers.length; i++) {
ZipObserver<T, R> zs = observers[i];
if (values[i] == null) {
// 尝试从队列取数据
T v = zs.queue.poll();
if (v != null) {
values[i] = v;
} else {
allHaveValues = false;
}
}
}
if (allHaveValues) {
try {
// 应用zipper函数组合数据
R r = zipper.apply(values.clone());
downstream.onNext(r);
} catch (Throwable ex) {
// 错误处理
}
// 清空当前值
Arrays.fill(values, null);
// 请求更多数据
for (ZipObserver<?, ?> zs : observers) {
zs.request(1);
}
}
missing = addAndGet(-missing);
if (missing == 0) break;
}
}
}
static final class ZipObserver<T, R> implements Observer<T> {
final ZipCoordinator<T, R> parent;
final SimpleQueue<T> queue;
ZipObserver(ZipCoordinator<T, R> parent, int bufferSize, boolean delayError) {
this.parent = parent;
this.queue = new SpscLinkedArrayQueue<>(bufferSize);
}
@Override
public void onNext(T t) {
queue.offer(t);
parent.drain(); // 触发协调器处理
}
}
zip 工作流程:
- 为每个源创建ZipObserver
- 每个源的数据存入独立队列
- ZipCoordinator检查所有队列是否有数据
- 所有队列都有数据时,应用zipper函数
- 向下游发送组合结果
- 请求每个源的下一项数据
1.2 combineLatest() 实现原理
public static <T, R> Observable<R> combineLatest(
ObservableSource<? extends T>[] sources,
Function<? super Object[], ? extends R> combiner) {
return new ObservableCombineLatest<>(sources, combiner, bufferSize(), false);
}
ObservableCombineLatest 核心机制:
static final class CombineLatestCoordinator<T, R>
extends AtomicInteger
implements Disposable {
final Observer<? super R> downstream;
final Function<? super Object[], ? extends R> combiner;
final CombineLatestObserver<T, R>[] observers;
final Object[] latest; // 存储每个源的最新值
@Override
public void onNext(int index, T value) {
boolean shouldEmit = false;
synchronized (this) {
// 1. 更新最新值
latest[index] = value;
hasValue[index] = true;
// 2. 检查是否所有源都有值
int localComplete = complete;
if (allHasValue()) {
// 3. 应用组合函数
R r = combiner.apply(latest.clone());
shouldEmit = true;
}
}
if (shouldEmit) {
// 4. 发送组合结果
downstream.onNext(r);
}
}
}
与zip的区别:
| 特性 | zip | combineLatest |
|---|---|---|
| 触发条件 | 所有源都有新数据 | 任意源有新数据 |
| 数据对齐 | 严格按顺序配对 | 使用最新数据 |
| 内存占用 | 需要队列缓冲 | 只需存储最新值 |
| 适用场景 | 严格同步数据流 | 状态组合 |
2. 错误处理机制
2.1 onErrorResumeNext() 实现
public final Observable<T> onErrorResumeNext(
Function<? super Throwable, ? extends ObservableSource<? extends T>> resumeFunction) {
return new ObservableOnErrorNext<>(this, resumeFunction, false);
}
ObservableOnErrorNext 源码:
public final class ObservableOnErrorNext<T> extends AbstractObservableWithUpstream<T, T> {
final Function<? super Throwable, ? extends ObservableSource<? extends T>> resumeFunction;
final boolean allowFatal;
@Override
public void subscribeActual(Observer<? super T> t) {
source.subscribe(new OnErrorNextObserver<>(t, resumeFunction, allowFatal));
}
static final class OnErrorNextObserver<T> implements Observer<T> {
final Observer<? super T> downstream;
final Function<? super Throwable, ? extends ObservableSource<? extends T>> resumeFunction;
@Override
public void onError(Throwable t) {
ObservableSource<? extends T> p;
try {
// 1. 应用恢复函数
p = resumeFunction.apply(t);
} catch (Throwable e) {
// 2. 恢复函数本身出错
downstream.onError(e);
return;
}
// 3. 订阅备用数据源
p.subscribe(new ResumeObserver(downstream));
}
static final class ResumeObserver<T> implements Observer<T> {
final Observer<? super T> downstream;
ResumeObserver(Observer<? super T> downstream) {
this.downstream = downstream;
}
@Override
public void onNext(T t) {
downstream.onNext(t);
}
}
}
}
2.2 错误处理操作符对比
| 操作符 | 作用 | 适用场景 |
|---|---|---|
onErrorReturn() | 返回静态值 | 简单恢复 |
onErrorResumeNext() | 切换备用Observable | 复杂恢复 |
retry() | 重试原始Observable | 临时错误 |
retryWhen() | 条件重试 | 带延迟的重试 |
3. 并发模型解析
3.1 observeOn 并发模型
关键设计:
// ObservableObserveOn.java
protected void schedule() {
if (getAndIncrement() == 0) {
// 使用Worker调度
worker.schedule(this);
}
}
@Override
public void run() {
// 在目标线程处理事件
drainNormal();
}
void drainNormal() {
int missed = 1;
final SimpleQueue<T> q = queue;
for (;;) {
// 从队列取数据
T v = q.poll();
if (v != null) {
// 实际调用下游Observer
downstream.onNext(v);
}
// 处理完成和错误...
missed = addAndGet(-missed);
if (missed == 0) break;
}
}
并发控制机制:
- 原子计数器:
getAndIncrement()保证只有一个线程执行drain - 队列缓冲:使用
SpscLinkedArrayQueue高效队列 - 批处理:单次循环处理多个事件
3.2 subscribeOn 线程穿透问题
问题现象:
observable
.subscribeOn(Schedulers.io()) // 有效
.map(v -> { /* 在io线程 */ })
.subscribeOn(Schedulers.computation()) // 无效
源码解析:
// ObservableSubscribeOn.java
public void subscribeActual(final Observer<? super T> observer) {
// 创建中间Observer
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<>(observer);
// 调度订阅任务
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}
原因:
subscribeOn只影响订阅操作(source.subscribe())- 后续操作符在上游线程执行
- 只有第一个
subscribeOn决定订阅线程
4. 高级并发模式
4.1 并行处理模式
Observable.range(1, 100)
.flatMap(i ->
Observable.just(i)
.subscribeOn(Schedulers.computation()) // 并行执行
.map(this::heavyComputation)
)
.toList()
.subscribe(results -> { /* 处理结果 */ });
4.2 并发控制模式
// 限制并发数为4
Observable.range(1, 100)
.flatMap(i ->
loadItem(i).subscribeOn(Schedulers.io()),
4 // 最大并发数
)
.subscribe();
flatMap 并发控制源码:
// ObservableFlatMap.java
public void onNext(T t) {
// 应用mapper函数
ObservableSource<? extends U> p = mapper.apply(t);
if (active.get() < maxConcurrency) {
// 未达并发上限
active.getAndIncrement();
p.subscribe(new InnerObserver());
} else {
// 加入等待队列
queue.offer(p);
}
}
void innerComplete() {
active.decrementAndGet();
if (!queue.isEmpty()) {
// 从队列取出等待任务
ObservableSource<? extends U> p = queue.poll();
active.getAndIncrement();
p.subscribe(new InnerObserver());
}
}
4.3 线程隔离模式
// 为不同类型操作分配专用线程池
Scheduler dbScheduler = Schedulers.from(Executors.newFixedThreadPool(2));
Scheduler networkScheduler = Schedulers.from(Executors.newFixedThreadPool(4));
Observable.just(userId)
.subscribeOn(dbScheduler)
.map(this::loadFromDatabase)
.observeOn(networkScheduler)
.flatMap(this::fetchRemoteData)
.observeOn(Schedulers.computation())
.map(this::processData)
.observeOn(AndroidSchedulers.mainThread())
.subscribe();
5. 并发陷阱与解决方案
5.1 线程安全问题
错误示例:
List<String> results = new ArrayList<>();
Observable.range(1, 1000)
.parallel() // 并行处理
.runOn(Schedulers.computation())
.map(i -> "Item " + i)
.doOnNext(results::add) // 多线程修改集合!
.sequential()
.subscribe();
解决方案:
// 使用线程安全集合
List<String> results = Collections.synchronizedList(new ArrayList<>());
// 或者使用collect操作符
Observable.range(1, 1000)
.parallel()
.runOn(Schedulers.computation())
.map(i -> "Item " + i)
.sequential()
.collect(ArrayList::new, ArrayList::add)
.subscribe();
5.2 死锁问题
风险场景:
Observable.create(emitter -> {
new Thread(() -> {
String result = blockingOperation(); // 阻塞操作
emitter.onNext(result);
}).start();
})
.subscribeOn(Schedulers.io()) // 使用有限线程池
.subscribe();
解决方案:
// 使用专用线程池
Scheduler unboundedScheduler = Schedulers.from(Executors.newCachedThreadPool());
Observable.create(emitter -> {
// 在无界线程池执行阻塞操作
unboundedScheduler.scheduleDirect(() -> {
String result = blockingOperation();
emitter.onNext(result);
});
})
.subscribe();
5.3 资源竞争问题
错误示例:
int counter = 0; // 共享状态
Observable.range(1, 1000)
.parallel()
.runOn(Schedulers.computation())
.doOnNext(i -> counter++) // 非原子操作!
.sequential()
.subscribe();
解决方案:
// 使用原子变量
AtomicInteger counter = new AtomicInteger();
Observable.range(1, 1000)
.parallel()
.runOn(Schedulers.computation())
.doOnNext(i -> counter.incrementAndGet())
.sequential()
.subscribe();
本章总结
-
组合操作符:
zip:严格对齐多个流,适合同步数据combineLatest:任意源更新时组合最新值,适合状态管理- 使用协调器模式管理多流协作
-
错误处理:
onErrorResumeNext:切换到备用Observable- 错误处理操作符形成安全网,防止崩溃
- 区分可恢复错误与致命错误
-
并发模型:
observeOn:使用队列+线程调度实现线程切换subscribeOn:只影响订阅起点- 并发控制:flatMap的maxConcurrency参数
-
高级模式:
- 并行处理:flatMap + subscribeOn
- 线程隔离:专用调度器分配
- 资源竞争:使用原子变量或线程安全集合
-
并发陷阱:
- 线程安全问题:共享可变状态
- 死锁风险:阻塞有限线程池
- 资源竞争:非原子操作
核心洞察:RxJava的并发模型建立在Scheduler和队列机制之上,通过操作符组合实现复杂的并发模式。理解底层机制有助于避免常见并发陷阱,构建高性能的异步应用。
在下一章中,我们将聚焦Android平台的RxJava实战优化,包括内存泄漏防护、RxBinding原理分析以及Retrofit集成最佳实践