第四章:Rxjava 高阶功能与并发模型

39 阅读6分钟

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 工作流程

  1. 为每个源创建ZipObserver
  2. 每个源的数据存入独立队列
  3. ZipCoordinator检查所有队列是否有数据
  4. 所有队列都有数据时,应用zipper函数
  5. 向下游发送组合结果
  6. 请求每个源的下一项数据

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的区别

特性zipcombineLatest
触发条件所有源都有新数据任意源有新数据
数据对齐严格按顺序配对使用最新数据
内存占用需要队列缓冲只需存储最新值
适用场景严格同步数据流状态组合

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;
    }
}

并发控制机制

  1. 原子计数器getAndIncrement()保证只有一个线程执行drain
  2. 队列缓冲:使用SpscLinkedArrayQueue高效队列
  3. 批处理:单次循环处理多个事件

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();

本章总结

  1. 组合操作符

    • zip:严格对齐多个流,适合同步数据
    • combineLatest:任意源更新时组合最新值,适合状态管理
    • 使用协调器模式管理多流协作
  2. 错误处理

    • onErrorResumeNext:切换到备用Observable
    • 错误处理操作符形成安全网,防止崩溃
    • 区分可恢复错误与致命错误
  3. 并发模型

    • observeOn:使用队列+线程调度实现线程切换
    • subscribeOn:只影响订阅起点
    • 并发控制:flatMap的maxConcurrency参数
  4. 高级模式

    • 并行处理:flatMap + subscribeOn
    • 线程隔离:专用调度器分配
    • 资源竞争:使用原子变量或线程安全集合
  5. 并发陷阱

    • 线程安全问题:共享可变状态
    • 死锁风险:阻塞有限线程池
    • 资源竞争:非原子操作

核心洞察:RxJava的并发模型建立在Scheduler和队列机制之上,通过操作符组合实现复杂的并发模式。理解底层机制有助于避免常见并发陷阱,构建高性能的异步应用。

在下一章中,我们将聚焦Android平台的RxJava实战优化,包括内存泄漏防护、RxBinding原理分析以及Retrofit集成最佳实践