RxJava - 观察者在一段时间后没有得到onNext()项目

时间:2016-06-08 21:49:25

标签: java rx-java reactive-programming

我有一个由几个互连组件组成的系统。一切都运作良好,但经过一段时间后,一些观察者停止接收由观察者的onNext()发送的物品。

简化的场景是这样的:我有 Component1.start() - >使用Observable.create(...).subscribeOn().observeOn().publish()创建一个ConnectableObservable,并订阅Component2。之后,它连接()s。这个observable在一个循环中发出一些项目,然后在它完成时调用s.onComplete()

Component2实现了Observer。此外,它还有一个运行while(true)循环的ConnectableObservable。当它在由Component1调用的onNext()中获取值时,它使用自己的ConnectableObservable通知Component0。 (注意我也用PublishSubject实现了它们,同样的事情发生了。)

Component1.start() //Creates Component1's ConnectableObservable, subscribes Component2 and starts running with connect();

Component1.connectableObservable -> onNext() ---> Component2 

Component2.connectableObservable -> onNext() ---> Component0

当Component0.onNext()获取特定项目(经过100次迭代)后,它会停止Component1.observable,使其退出循环并调用onComplete()。

一段时间后,Component0调用Component1.start(),一切都重新开始。

我看到的是,当一切正常时 Component1.observable.onNext()调用rx.internal.operators.OperatorSubscribeOn.......subscriber.onNext()

rx.internal.operators.OperatorSubscribeOn

@Override
public void call(final Subscriber<? super T> subscriber) {
    final Worker inner = scheduler.createWorker();
    subscriber.add(inner);

    inner.schedule(new Action0() {
        @Override
        public void call() {
            final Thread t = Thread.currentThread();

            Subscriber<T> s = new Subscriber<T>(subscriber) {
                @Override
                public void onNext(T t) {
                    subscriber.onNext(t);

subscriber.onNext()是内部类private static final class ObserveOnSubscriber<T>,最后调用schedule():

@Override
public void onNext(final T t) {
    if (isUnsubscribed() || finished) {
        return;
    }
    if (!queue.offer(on.next(t))) {
        onError(new MissingBackpressureException());
        return;
    }
    schedule();
}

schedule()是

protected void schedule() {
    if (counter.getAndIncrement() == 0) {
        recursiveScheduler.schedule(this);
    }
}

计数器为0,因此调用recursiveScheduler.schedule(this);并且Component2获取该项目。

现在,当它停止工作时发生的事情是计数器不再是0 ,实际上每次调用都会增加它。因此,recursiveScheduler.schedule(this);永远不会被调用,而Component2也不会得到任何东西。

这可能是什么原因?为什么计数器0会在某个时刻开始增加?

更新:在源代码中挖掘我见过以下内容:在调用schedule()之后,有一个调度任务调用下面的代码,当项目没有时减少计数器错过:

private static final class ObserveOnSubscriber<T> extends Subscriber<T> implements Action0 {

    // only execute this from schedule()
    @Override
    public void call() {
        ...
            emitted = currentEmission;
            missed = counter.addAndGet(-missed);
            if (missed == 0L) {
                break;
            }

据此,由于项目被遗漏,计数器增加,然后后续项目也被遗漏。

错过商品的原因是什么?

我注意到一些奇怪的事情。如果我从程序中删除任何其他(未提及的)可观察量,则不会错过任何项目。他们将Component0作为观察者并在他们自己的subscribeOn()线程中生成他们的项目,所以我看不出它们如何影响这种情况。

更新2:我一直试图找出会发生什么。当我Component1.connectableObservable.connect()时,它最终会调用private static final class ObserveOnSubscriber<T> extends Subscriber<T> implements Action0 -> init()

这里调用schedule():

void init() {
            // don't want this code in the constructor because `this` can escape through the 
            // setProducer call
            Subscriber<? super T> localChild = child;

            localChild.setProducer(new Producer() {

                @Override
                public void request(long n) {
                    if (n > 0L) {
                        BackpressureUtils.getAndAddRequest(requested, n);
                        schedule();

正确的行为在schedule()之后离开OperatorObserveOn.counter = 0。当它不再起作用时,scheduler()会增加+1 OperatorObserveOn.counter的值。

1 个答案:

答案 0 :(得分:0)

获取每个订阅的观察者并创建一个监听器,告诉您何时一个观察者取消订阅observable,然后您就可以理解为什么会发生这种情况。

在你的情况下,无论如何我会看看接力,因为你不必取消订阅你的观察它更安全,你可以确定它永远不会停止发射事件。

看看这个例子。

https://github.com/politrons/reactive/blob/master/src/test/java/rx/relay/Relay.java