rxjava 3.0 BehaviorProcessor底层源代码分析

359 阅读8分钟

这段代码是 RxJava 中 BehaviorProcessor 类的实现,它是一个特殊的处理器(Processor),可以缓存并向新的订阅者发出最后一个观察到的项以及所有后续的项。以下是对该类的详细分析:

类的结构和字段

  1. 字段

    • subscribers: 存储当前所有订阅者的原子引用数组。
    • EMPTY, TERMINATED: 表示订阅者数组的两种特殊状态。
    • lock, readLock, writeLock: 读写锁,用于确保线程安全的读写操作。
    • value: 原子引用,存储当前缓存的值。
    • terminalEvent: 原子引用,存储终止事件(错误或完成)。
    • index: 一个简单的计数器,用于跟踪项的顺序。
  2. 静态方法

    • create(): 创建一个新的 BehaviorProcessor 实例,不包含初始值。
    • createDefault(T defaultValue): 创建一个包含默认初始值的 BehaviorProcessor 实例。
  3. 构造函数

    • 无参数构造函数:初始化字段。
    • 带默认值的构造函数:调用无参数构造函数,并设置初始值。

主要方法

  1. 订阅和取消订阅

    • subscribeActual(Subscriber<? super T> s): 订阅者订阅时被调用,创建 BehaviorSubscription 实例并尝试添加到订阅者数组。
    • remove(BehaviorSubscription<T> rs): 从订阅者数组中移除指定的订阅者。
  2. 事件处理

    • onSubscribe(Subscription s): 处理订阅事件,但实际上此类通常作为事件源,不需要调用该方法。
    • onNext(T t): 处理下一个事件,将事件传播给所有订阅者。
    • onError(Throwable t): 处理错误事件,将错误事件传播给所有订阅者,并进入终止状态。
    • onComplete(): 处理完成事件,将完成事件传播给所有订阅者,并进入终止状态。
    • offer(T t): 尝试向所有订阅者发送事件,如果所有订阅者都已请求,则返回 true,否则返回 false。
  3. 状态检查

    • hasSubscribers(): 检查是否有订阅者。
    • getThrowable(): 获取终止时的错误(如果有)。
    • getValue(): 获取当前缓存的值。
    • hasComplete(): 检查是否已完成。
    • hasThrowable(): 检查是否有错误。
    • hasValue(): 检查是否有缓存值。
  4. 内部辅助方法

    • add(BehaviorSubscription<T> rs): 添加订阅者到订阅者数组。
    • terminate(Object terminalValue): 终止处理器,并返回终止时的订阅者数组。
    • setCurrent(Object o): 设置当前缓存值,同时增加索引。

内部类 BehaviorSubscription

BehaviorSubscriptionSubscription 的实现,代表一个订阅关系。其主要职责是处理订阅者的请求、取消订阅和事件的发送。

  1. 字段

    • downstream: 实际的订阅者。
    • state: 所属的 BehaviorProcessor 实例。
    • next, emitting, fastPath, cancelled: 标志位,控制订阅状态和事件发送。
    • queue: 用于存储待发送的事件。
    • index: 当前事件的索引。
  2. 方法

    • request(long n): 处理订阅者的请求。
    • cancel(): 取消订阅。
    • emitFirst(): 向新的订阅者发送缓存的值。
    • emitNext(Object value, long stateIndex): 向订阅者发送下一个事件。
    • test(Object o): 处理事件,并根据订阅者的状态决定是否继续发送。
    • emitLoop(): 循环发送缓存的事件。
    • isFull(): 检查订阅者是否已满(请求数为零)。

BehaviorProcessor 是 RxJava 中一种强大的处理器,允许缓存并向新的订阅者发送最后一个事件和所有后续事件。它利用线程安全的原子操作和锁机制,确保在并发环境中的安全性。通过提供多种状态检查方法和事件处理方法,它为开发者提供了丰富的功能和灵活性。

联系我

补充: 这段代码实现了 RxJava 中的 BehaviorProcessor 类。它是一个处理器,用于缓存最近一次的事件并向新订阅者发送,同时向所有订阅者发送后续事件。以下是对订阅和事件处理的详细分解和分析:

1. 订阅相关的方法

subscribeActual

这个方法在订阅者订阅时被调用:

@Override
protected void subscribeActual(@NonNull Subscriber<@NonNull ? super T> s) {
    BehaviorSubscription<T> bs = new BehaviorSubscription<>(s, this);
    s.onSubscribe(bs);
    if (add(bs)) {
        if (bs.cancelled) {
            remove(bs);
        } else {
            bs.emitFirst();
        }
    } else {
        Throwable ex = terminalEvent.get();
        if (ex == ExceptionHelper.TERMINATED) {
            s.onComplete();
        } else {
            s.onError(ex);
        }
    }
}
  • 创建一个新的 BehaviorSubscription 实例,表示一个订阅关系。
  • 调用订阅者的 onSubscribe 方法,将订阅关系传递给订阅者。
  • 尝试将订阅关系添加到 subscribers 数组中。如果添加成功且订阅未取消,调用 emitFirst 发送缓存的值。如果订阅已经取消,则将其从 subscribers 数组中移除。
  • 如果处理器已经终止,则向订阅者发送终止事件。

addremove

这些方法用于管理订阅者:

boolean add(BehaviorSubscription<T> rs) {
    for (;;) {
        BehaviorSubscription<T>[] a = subscribers.get();
        if (a == TERMINATED) {
            return false;
        }
        int len = a.length;
        @SuppressWarnings("unchecked")
        BehaviorSubscription<T>[] b = new BehaviorSubscription[len + 1];
        System.arraycopy(a, 0, b, 0, len);
        b[len] = rs;
        if (subscribers.compareAndSet(a, b)) {
            return true;
        }
    }
}

@SuppressWarnings("unchecked")
void remove(BehaviorSubscription<T> rs) {
    for (;;) {
        BehaviorSubscription<T>[] a = subscribers.get();
        int len = a.length;
        if (len == 0) {
            return;
        }
        int j = -1;
        for (int i = 0; i < len; i++) {
            if (a[i] == rs) {
                j = i;
                break;
            }
        }

        if (j < 0) {
            return;
        }
        BehaviorSubscription<T>[] b;
        if (len == 1) {
            b = EMPTY;
        } else {
            b = new BehaviorSubscription[len - 1];
            System.arraycopy(a, 0, b, 0, j);
            System.arraycopy(a, j + 1, b, j, len - j - 1);
        }
        if (subscribers.compareAndSet(a, b)) {
            return;
        }
    }
}
  • add 方法将新的订阅关系添加到 subscribers 数组中。
  • remove 方法从 subscribers 数组中移除指定的订阅关系。

2. 事件处理相关的方法

onSubscribe

@Override
public void onSubscribe(@NonNull Subscription s) {
    if (terminalEvent.get() != null) {
        s.cancel();
        return;
    }
    s.request(Long.MAX_VALUE);
}
  • 处理订阅事件。如果处理器已经终止,取消订阅。否则,请求 Long.MAX_VALUE 表示无限量请求。

onNext

@Override
public void onNext(@NonNull T t) {
    ExceptionHelper.nullCheck(t, "onNext called with a null value.");

    if (terminalEvent.get() != null) {
        return;
    }
    Object o = NotificationLite.next(t);
    setCurrent(o);
    for (BehaviorSubscription<T> bs : subscribers.get()) {
        bs.emitNext(o, index);
    }
}
  • 处理下一个事件。首先检查值是否为空,如果为空则抛出异常。
  • 检查处理器是否已终止,如果是,则返回。
  • 创建事件对象,并更新当前值。
  • 将事件传播给所有订阅者。

onError

@Override
public void onError(@NonNull Throwable t) {
    ExceptionHelper.nullCheck(t, "onError called with a null Throwable.");
    if (!terminalEvent.compareAndSet(null, t)) {
        RxJavaPlugins.onError(t);
        return;
    }
    Object o = NotificationLite.error(t);
    for (BehaviorSubscription<T> bs : terminate(o)) {
        bs.emitNext(o, index);
    }
}
  • 处理错误事件。首先检查错误是否为空,如果为空则抛出异常。
  • 更新终止事件为错误。如果已经有终止事件,则将错误报告给全局错误处理器。
  • 创建错误事件对象,并将其传播给所有订阅者。

onComplete

@Override
public void onComplete() {
    if (!terminalEvent.compareAndSet(null, ExceptionHelper.TERMINATED)) {
        return;
    }
    Object o = NotificationLite.complete();
    for (BehaviorSubscription<T> bs : terminate(o)) {
        bs.emitNext(o, index);  // relaxed read okay since this is the only mutator thread
    }
}
  • 处理完成事件。更新终止事件为完成。
  • 创建完成事件对象,并将其传播给所有订阅者。

3. 辅助方法

setCurrent

void setCurrent(Object o) {
    Lock wl = writeLock;
    wl.lock();
    index++;
    value.lazySet(o);
    wl.unlock();
}
  • 设置当前值,并更新索引。

terminate

@SuppressWarnings("unchecked")
BehaviorSubscription<T>[] terminate(Object terminalValue) {
    setCurrent(terminalValue);
    return subscribers.getAndSet(TERMINATED);
}
  • 终止处理器,并返回终止时的订阅者数组。

4. 内部类 BehaviorSubscription

字段

  • downstream: 实际的订阅者。
  • state: 所属的 BehaviorProcessor 实例。
  • next, emitting, fastPath, cancelled: 标志位,控制订阅状态和事件发送。
  • queue: 用于存储待发送的事件。
  • index: 当前事件的索引。

方法

requestcancel
@Override
public void request(long n) {
    if (SubscriptionHelper.validate(n)) {
        BackpressureHelper.add(this, n);
    }
}

@Override
public void cancel() {
    if (!cancelled) {
        cancelled = true;
        state.remove(this);
    }
}
  • request 处理订阅者的请求。
  • cancel 取消订阅。
emitFirstemitNext
void emitFirst() {
    if (cancelled) {
        return;
    }
    Object o;
    synchronized (this) {
        if (cancelled) {
            return;
        }
        if (next) {
            return;
        }

        BehaviorProcessor<T> s = state;

        Lock readLock = s.readLock;
        readLock.lock();
        index = s.index;
        o = s.value.get();
        readLock.unlock();

        emitting = o != null;
        next = true;
    }

    if (o != null) {
        if (test(o)) {
            return;
        }

        emitLoop();
    }
}

void emitNext(Object value, long stateIndex) {
    if (cancelled) {
        return;
    }
    if (!fastPath) {
        synchronized (this) {
            if (cancelled) {
                return;
            }
            if (index == stateIndex) {
                return;
            }
            if (emitting) {
                AppendOnlyLinkedArrayList<Object> q = queue;
                if (q == null) {
                    q = new AppendOnlyLinkedArrayList<>(4);
                    queue = q;
                }
                q.add(value);
                return;
            }
            next = true;
        }
        fastPath = true;
    }

    test(value);
}
  • emitFirst 向新的订阅者发送缓存的值。
  • emitNext 向订阅者发送下一个事件。
testemitLoop
@Override
public boolean test(Object o) {
    if (cancelled) {
        return true;
    }

    if (NotificationLite.isComplete(o)) {
        downstream.onComplete();
        return true;
    } else if (NotificationLite.isError(o)) {
        downstream.onError(NotificationLite.getError(o));
        return true;
    }

    long r = get();
    if (r != 0L) {
        downstream.onNext(NotificationLite.<T>getValue(o));
        if (r != Long.MAX_VALUE) {
            decrementAndGet();
        }
        return false;
    }
    cancel();
    downstream.onError(new MissingBackpressureException("Could not deliver value due to lack of requests"));
    return true;
}

void emitLoop() {
    for (;;) {
        if (cancelled) {
            return;
        }
        AppendOnlyLinkedArrayList<Object> q;
        synchronized (this) {
            q = queue;
            if (q == null) {
                emitting = false;

联系我

还是有一点不明白,subscribeActual这个方法在订阅者订阅时如何被调用, 再分析: 在 RxJava 的架构中,subscribeActual 方法是由 Flowable.subscribe 方法间接调用的。当你创建一个 Flowable 并调用 subscribe 方法时,RxJava 框架内部会进行一系列操作,最终调用到 subscribeActual 方法。以下是一个简单的调用链,展示了 subscribeActual 方法如何在订阅者订阅时被调用。

调用链

  1. 用户代码调用 subscribe 方法:
BehaviorProcessor<Object> processor = BehaviorProcessor.create();
processor.subscribe(subscriber);
  1. Flowable.subscribe 方法:

当你调用 subscribe 方法时,实际上调用的是 Flowable 类中的 subscribe 方法。

@Override
public final void subscribe(Subscriber<? super T> s) {
    Objects.requireNonNull(s, "s is null");
    try {
        Subscriber<? super T> z = RxJavaPlugins.onSubscribe(this, s);
        Objects.requireNonNull(z, "Plugin returned null Subscriber");
        subscribeActual(z);
    } catch (NullPointerException e) { // NOPMD
        throw e;
    } catch (Throwable e) {
        Exceptions.throwIfFatal(e);
        // can't call onError because no way to know if a subscription has happened so can't call cancel
        RxJavaPlugins.onError(e);
        throw ExceptionHelper.wrapOrThrow(e);
    }
}

这个方法做了以下几件事:

  • 确保订阅者 s 不为空。
  • 调用 RxJavaPlugins.onSubscribe 方法,这是一个钩子方法,允许 RxJava 插件处理订阅逻辑。
  • 调用 subscribeActual(z),这里的 z 是经过插件处理后的订阅者。
  1. 调用 BehaviorProcessor.subscribeActual 方法:

subscribeActual 方法在 BehaviorProcessor 类中被重写,它会处理实际的订阅逻辑。

@Override
protected void subscribeActual(@NonNull Subscriber<@NonNull ? super T> s) {
    BehaviorSubscription<T> bs = new BehaviorSubscription<>(s, this);
    s.onSubscribe(bs);
    if (add(bs)) {
        if (bs.cancelled) {
            remove(bs);
        } else {
            bs.emitFirst();
        }
    } else {
        Throwable ex = terminalEvent.get();
        if (ex == ExceptionHelper.TERMINATED) {
            s.onComplete();
        } else {
            s.onError(ex);
        }
    }
}

具体过程

  1. 创建 BehaviorSubscription 实例:
BehaviorSubscription<T> bs = new BehaviorSubscription<>(s, this);

这里 BehaviorSubscription 是一个内部类,表示一个具体的订阅关系。

  1. 调用订阅者的 onSubscribe 方法:
s.onSubscribe(bs);

BehaviorSubscription 实例传递给订阅者。

  1. BehaviorSubscription 添加到订阅者列表:
if (add(bs)) {
    if (bs.cancelled) {
        remove(bs);
    } else {
        bs.emitFirst();
    }
}
  • 如果添加成功且订阅未取消,调用 emitFirst 方法发送缓存的值。
  • 如果订阅已经取消,则将其从 subscribers 列表中移除。
  1. 处理终止状态:
else {
    Throwable ex = terminalEvent.get();
    if (ex == ExceptionHelper.TERMINATED) {
        s.onComplete();
    } else {
        s.onError(ex);
    }
}

如果处理器已经终止,则向订阅者发送终止事件。

在 RxJava 中,subscribeActual 方法在订阅者调用 subscribe 方法时被框架内部调用。这个过程涉及一系列方法调用和检查,确保订阅关系被正确建立,并处理可能的并发和终止状态。通过这种设计,RxJava 提供了一个灵活且强大的异步编程模型。

联系我