Rxjava中的线程切换

351 阅读9分钟

我们先以下面的demo为例,来解释Rxjava的整个工作流程。

 public void start() {
    Observable<Integer> observable1 = Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
            Log.d(TAG, "当前线程名称 " + Thread.currentThread().getName());
            emitter.onNext(1);
            emitter.onNext(2);
            emitter.onNext(3);
            emitter.onComplete();
        }
    });
    
    Observer<Integer> observer = new Observer<Integer>() {
        @Override
        public void onSubscribe(Disposable d) {

            Log.d(TAG, "开始采用subscribe连接 " + Thread.currentThread().getName());
        }

        @Override
        public void onNext(Integer value) {
            Log.d(TAG, "观察者线程在 " + Thread.currentThread().getName());
            Log.d(TAG, "对Next事件作出响应" + value);
        }

        @Override
        public void onError(Throwable e) {
            Log.d(TAG, "对Error事件作出响应");
        }

        @Override
        public void onComplete() {
            Log.d(TAG, "对Complete事件作出响应");
        }
    };
  observable1
            .subscribeOn(Schedulers.newThread())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .observeOn(Schedulers.newThread())
            .subscribe(observer);

subscribe前的操作符

@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> subscribeOn(Scheduler scheduler) {
    ObjectHelper.requireNonNull(scheduler, "scheduler is null");
    return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}
  1. 第一个操作符.subscribeOn(Observable.java)
    @SchedulerSupport(SchedulerSupport.CUSTOM)
    public final Observable<T> subscribeOn(Scheduler scheduler) {
        ObjectHelper.requireNonNull(scheduler, "scheduler is null");
        return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
    }

ObservableSubscribeOn继承 AbstractObservableWithUpstream,是对Observable的包装 此时,执行完new ObservableSubscribeOn之后, Observable的结构如下

  1. 第二个操作符.subscribeOn(Observable.java) 其基本执行流程同上,只是Scheduler不一样,那么还是对Observable的进一步包装,此时,执行完new ObservableSubscribeOn之后, Observable的结构如下

  1. 第三个操作符.observeOn(Observable.java)
    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.CUSTOM)
    public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
        ObjectHelper.requireNonNull(scheduler, "scheduler is null");
        ObjectHelper.verifyPositive(bufferSize, "bufferSize");
        return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
    }

将上述的 Observable再次包装成 ObservableObserveOn

    public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean delayError, int bufferSize) {
        super(source);
        this.scheduler = scheduler;
        this.delayError = delayError;
        this.bufferSize = bufferSize;
    }

此时,执行完new ObservableObserveOn, Observable的结构如下

  1. 第四个操作符.observeOn(Observable.java)

和第三步执行一样,只是将第三步的Observable继续包装,那么执行完的Observable机构如下

总结一下: 在调用Subscribe之前的操作符都是对Observable的包装,那么最里层的Observable就是demo里的observable1了。

subscribe流程

这里需要注意的是,每一个操作符都都对应了一个静态内部类的Observer,操作符向下包装Observable,向上订阅过程中用对应的静态内部类包装Observer,理解这一点非常重要。

.subscribe(observer);

这里的observer就是在程序中实际声明的observer,接下来看下具体的订阅流程

public final void subscribe(Observer<? super T> observer) {
        ObjectHelper.requireNonNull(observer, "observer is null");
        try {
        subscribeActual 的具体执行者就是上述中最后的包装的Observable,ObservableObserveOn
            subscribeActual(observer);
        }
    }
  1. 接下来看下ObservableObserveOn的subscribeActual方法都干了什么
 @Override
    protected void subscribeActual(Observer<? super T> observer) {
        if (scheduler instanceof TrampolineScheduler) {
            source.subscribe(observer);
        } else {
         //scheduler 为最后生成时的NewThreadScheduler
            Scheduler.Worker w = scheduler.createWorker();
         // 对observer的第一次包装
            source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
        }
    }
    
    可以看到对定义的observer和worker进行一次包装
   ObserveOnObserver(Observer<? super T> actual, Scheduler.Worker worker, boolean delayError, int bufferSize) {
            this.downstream = actual;
            this.worker = worker;
            this.delayError = delayError;
            this.bufferSize = bufferSize;
        }
  1. 那么现在的Observer的结构是这个样子的

然后作为新的observer传入,那么执行source.subscribe是,此时的source是上述脑图中的source(ObservableObserveOn)--1,执行过程和上述一样,那么执行完之后的observer是什么样的结构呢?看红色箭头所示

3. 继续执行source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize)); 此时的source对应的是ObservableSubscribeOn,如图下所示

 @Override
    public void subscribeActual(final Observer<? super T> observer) {
        final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(observer);

        observer.onSubscribe(parent);

        parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));

此过程对Observer再次包装,

结构如下,如红框所示

之前的observer变成了现在的downstream成员变量。

  1. observer.onSubscribe(parent); 随后传入的downstream(ObserveOnObserver)执行onSubscribe(parent),parent是SubscribeOnObserver
@Override
        public void onSubscribe(Disposable d) {
            if (DisposableHelper.validate(this.upstream, d)) {
                this.upstream = d;
               ** if条件不执行**
                if (d instanceof QueueDisposable) {
                    @SuppressWarnings("unchecked")
                    QueueDisposable<T> qd = (QueueDisposable<T>) d;

                    int m = qd.requestFusion(QueueDisposable.ANY | QueueDisposable.BOUNDARY);

                    if (m == QueueDisposable.SYNC) {
                        sourceMode = m;
                        queue = qd;
                        done = true;
                        downstream.onSubscribe(this);
                        schedule();
                        return;
                    }
                    if (m == QueueDisposable.ASYNC) {
                        sourceMode = m;
                        queue = qd;
                        downstream.onSubscribe(this);
                        return;
                    }
                }

                queue = new SpscLinkedArrayQueue<T>(bufferSize);
                执行这个downstream,这个downstream 还是个ObserveOnObserver,
                downstream.onSubscribe(this);
            }
        }
        
        

看上方注释,会再次调用ObserveOnObserver的onSubscribe方法,这里比较绕,需要画图才能清晰的理解。那么与上一次执行不同的是,此时的 if (d instanceof QueueDisposable)是满足条件的,因为此时d是ObserveOnObserver,而ObserveOnObserver继承了BasicIntQueueDisposable,所以这个if条件满足

static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T>`

因为本次执行结果不一样,所以再把代码发下

@Override
        public void onSubscribe(Disposable d) {
            if (DisposableHelper.validate(this.upstream, d)) {
                this.upstream = d;
                1. 满足条件,进入if语句
                if (d instanceof QueueDisposable) {
                    @SuppressWarnings("unchecked")
                    QueueDisposable<T> qd = (QueueDisposable<T>) d;
                    int m = qd.requestFusion(QueueDisposable.ANY | QueueDisposable.BOUNDARY);

                    if (m == QueueDisposable.SYNC) {
                        sourceMode = m;
                        queue = qd;
                        done = true;
                        downstream.onSubscribe(this);
                        schedule();
                        return;
                    }
                    3.经过计算 符合此条件,执行downstream的onSubscribe方法,退出
                    if (m == QueueDisposable.ASYNC) {
                        sourceMode = m;
                        queue = qd;
                        downstream.onSubscribe(this);
                        return;
                    }
                }

                queue = new SpscLinkedArrayQueue<T>(bufferSize);

                downstream.onSubscribe(this);
            }
        }
        
        2. 在这个Observer中outputFused设置为true,后面会用到
         @Override
        public int requestFusion(int mode) {
            if ((mode & ASYNC) != 0) {
                outputFused = true;
                return ASYNC;
            }
            return NONE;
        }

看上面的注释3,那么这个downstream其实就是我们程序中实际写的Observer了,也就是

 Observer<Integer> observer = new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {

                Log.d(TAG, "开始采用subscribe连接 " + Thread.currentThread().getName());
            }

所以,这里有个结论就是,Observer的onSubscire不受线程切换的限制,只和调用处的线程有关,因为执行到现在线程仍然在调用处的县城里。 会到4处,执行完Subscribe,我们看下面 parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent))); 根据函数的名字能够猜到这里就是线程切换的地方。我们跟进一下代码。

1). SubscribeTask 实现了Runnable接口,并且保存了Observer

final class SubscribeTask implements Runnable {
        private final SubscribeOnObserver<T> parent;

        SubscribeTask(SubscribeOnObserver<T> parent) {
            this.parent = parent;
        }

        @Override
        public void run() {
            source.subscribe(parent);
        }
    }

2)scheduler.scheduleDirec(xx)

@NonNull
    public Disposable scheduleDirect(@NonNull Runnable run) {
        return scheduleDirect(run, 0L, TimeUnit.NANOSECONDS);
    }
    
 @NonNull
    public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
    1. 这个Scheduler是个IoScheduler,这里返回一个IoScheduler的静态内部类型EventLoopWorker
        final Worker w = createWorker();

        final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
        2. 对传入的SubscribeTask进行包装,DisposeTask 也实现了Runnable接口
        DisposeTask task = new DisposeTask(decoratedRun, w);
        3.执行worker的schedule方法
        w.schedule(task, delay, unit);

        return task;
    }

继续跟进EventLoopWorker.java

public Disposable schedule(@NonNull Runnable action, long delayTime, @NonNull TimeUnit unit) {
            if (tasks.isDisposed()) {
                // don schedule, we are unsubscribed
                return EmptyDisposable.INSTANCE;
            }
            这里threadWorker是NewThreadWorker
            return threadWorker.scheduleActual(action, delayTime, unit, tasks);
        }

这里threadWorker是NewThreadWorker

跟进NewThreadWorke.java

 /**
     * Wraps the given runnable into a ScheduledRunnable and schedules it
     * on the underlying ScheduledExecutorService.
     * <p>If the schedule has been rejected, the ScheduledRunnable.wasScheduled will return
     * false.
     * @param run the runnable instance
     * @param delayTime the time to delay the execution
     * @param unit the time unit
     * @param parent the optional tracker parent to add the created ScheduledRunnable instance to before it gets scheduled
     * @return the ScheduledRunnable instance
     */
    @NonNull
    public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
        Runnable decoratedRun = RxJavaPlugins.onSchedule(run);

        ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);

        if (parent != null) {
            if (!parent.add(sr)) {
                return sr;
            }
        }

        Future<?> f;
        try {
            if (delayTime <= 0) {
            这里的executor是 ScheduledExecutorService executor;
                f = executor.submit((Callable<Object>)sr);
            } else {
                f = executor.schedule((Callable<Object>)sr, delayTime, unit);
            }
            sr.setFuture(f);
        } catch (RejectedExecutionException ex) {
            if (parent != null) {
                parent.remove(sr);
            }
            RxJavaPlugins.onError(ex);
        }

        return sr;
    }
  1. 所以线程就是在这里发生了切换,通过ScheduledExecutorService执行任务,那么这个任务是谁呢?就是一路传过来的SubsribeTask, 执行其run方法,也就是 source.subscribe(parent);

总结一下就是,ObservableSubscribeOn的方法继续将下游的Observer进行包装,然后切换线程,在新的线程中继续执行订阅,并将包装后的Observer继续传给上游。

  1. 那个由上述的结论推理下一个source,也就是ObservableSubscribeOn,还将继续执行上述过程,线程切换到Schedulers.newThread()中,这里就不再重复跟进了,直接在SubscribeTask的run方法中继续跟进.
  2. 由4可知,此时的也就是ObservableSubscribeOn执行完,此时source是也就是ObservableSubscribeOn的上游,也就是原始的source了,也就是ObservableCreate
public final class ObservableCreate<T> extends Observable<T> {
    final ObservableOnSubscribe<T> source;

    public ObservableCreate(ObservableOnSubscribe<T> source) {
        this.source = source;
    }

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
    1. 将oberver传入,包装成CreateEmitter
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        observer.onSubscribe(parent);

        try {
    2. 执行真正的订阅方法
            source.subscribe(parent);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
        }
   
 Observable<Integer> observable1 = Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
    3. 真正的执行的地方
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                Log.d(TAG, "当前线程名称 " + Thread.currentThread().getName());
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
                emitter.onComplete();
            }
        });

总结一下: 最终的被观察者所在的线程是在第一个SubscribeOn中设置的线程中执行的,所以subscribeOn多次切换线程虽然每次都生效,但是最后发送数据的是以第一个为准的。

以onNext为例,分析ObserveOn流程

  1. CreateEmitter的onNext
 @Override
        public void onNext(T t) {
            if (t == null) {
                onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
                return;
            }
            if (!isDisposed()) {
            1.   这个observer是上个source对应的静态内部类SubscribeOnObserver
                observer.onNext(t);
            }
        }
  1. SubscribeOnObserver的onNext
 @Override
        public void onNext(T t) {
        这个downstream是下一个SubscribeOnObserver
            downstream.onNext(t);
        }
  1. 根据上面的注释,会重复执行2的过程,此处省略,那么执行完后,这个downstream是谁呢,是ObserveOnObserver了,所以会执行ObserveOnObserver的onNext方法.
  @Override
        public void onNext(T t) {
            if (done) {
                return;
            }
        1.将数据存入queue中
            if (sourceMode != QueueDisposable.ASYNC) {
                queue.offer(t);
            }
        2.线程切换的地方   
            schedule();
        }
        
       void schedule() {
            if (getAndIncrement() == 0) {
        3.执行worker的schedule方法,这个worker是谁呢,是HandlerWorker
                worker.schedule(this);
            }
        }
  1. 所以在次进行线程切换,然后执行当前Observer的run方法

        @Override
        public void run() {
     1.   上面分析过outputFused 会为true,所以执行drainFused
            if (outputFused) {
                drainFused();
            } else {
                drainNormal();
            }
        }
        
        
      void drainFused() {
            int missed = 1;

            for (;;) {
                if (disposed) {
                    return;
                }

                boolean d = done;
                Throwable ex = error;

                if (!delayError && d && ex != null) {
                    disposed = true;
                    downstream.onError(error);
                    worker.dispose();
                    return;
                }
     2. 执行下游的downstream的onNext方法,这个downstream是谁? 还是ObserveOnObserver           
                downstream.onNext(null);

                if (d) {
                    disposed = true;
                    ex = error;
                    if (ex != null) {
                        downstream.onError(ex);
                    } else {
                        downstream.onComplete();
                    }
                    worker.dispose();
                    return;
                }

                missed = addAndGet(-missed);
                if (missed == 0) {
                    break;
                }
            }
        }   
  1. 根据上面注释2,再次执行线程切换,执行run方法
 @Override
        public void run() {
    1. 通步骤4不同的是,这时的outputFused是false,所以执行drainNormal()方法
            if (outputFused) {
                drainFused();
            } else {
                drainNormal();
            }
        }
    
     void drainNormal() {
            int missed = 1;

            final SimpleQueue<T> q = queue;
        2. 这个downstream是谁?这个就是我们具体声明的Observer啦
            final Observer<? super T> a = downstream;

            for (;;) {
                if (checkTerminated(done, q.isEmpty(), a)) {
                    return;
                }

                for (;;) {
                    boolean d = done;
                    T v;

                    try {
                        v = q.poll();
                    } catch (Throwable ex) {
                        Exceptions.throwIfFatal(ex);
                        disposed = true;
                        upstream.dispose();
                        q.clear();
                        a.onError(ex);
                        worker.dispose();
                        return;
                    }
                    boolean empty = v == null;

                    if (checkTerminated(d, empty, a)) {
                        return;
                    }

                    if (empty) {
                        break;
                    }

                    a.onNext(v);
                }

                missed = addAndGet(-missed);
                if (missed == 0) {
                    break;
                }
            }
        }
    
        Observer<Integer> observer = new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {

                Log.d(TAG, "开始采用subscribe连接 " + Thread.currentThread().getName());
            }

        3. 执行此方法
            @Override
            public void onNext(Integer value) {
                Log.d(TAG, "观察者线程在 " + Thread.currentThread().getName());
                Log.d(TAG, "对Next事件作出响应" + value);
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "对Error事件作出响应");
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "对Complete事件作出响应");
            }
        };

总结一下,虽然obserseOn线程可以指定多次,但是最终程序中声明的observer执行线程是在最后的observeOn的线程中执行的。

综合所述:

  1. 自上而下的每一个操作符都是对上游observerable的一次包装,生成新的Observable
  2. 执行subscribe后,相当于回溯调用上游的Observable的订阅流程,是对上游的Observable拆解,也是对下游的Observer的一次包装,在此过程中对subscribeOn中的线程切换,但是最终的Observable是在第一次切换的线程中
  3. 最终Observable执行onNext的方法时是对Observer的拆解,同时还进行了线程切换,最终observer的执行是在最后一次observeOn指定的线程中进行的