RxJava执行流程和线程切换原理

核心问题:

  • 为甚是被观察者订阅观察者
  • RxJava执行的流程
  • 线程切换的原理

为甚是被观察者订阅观察者

Observable.subscribe(Observer); 从字面上的理解是被观察者订阅观察者,比如报纸订阅了读者。但从开发者的角度来理解,就很正常 了。

RxJava这样设置的目的是为了流式Api的设计,还有就是Android中的观察者模式都是这样的写法,比如View.setOnClickListener(OnClickListener) : View就是被观察者,OnClickListener是观察者,他们通过setOnClickListener形成订阅关系。 一旦被观察者发生了什么事情(事件),就需要告知观察者,然后观察者会做出相应的措施。

RxJava执行的流程

从一个简单的示例代码说起:

 Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                e.onNext(1);
                e.onNext(2);
                e.onComplete();
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Integer>() {
                    private Disposable mD = null;

                    @Override
                    public void onSubscribe(Disposable d) {
                        mD = d;
                    }

                    @Override
                    public void onNext(Integer value) {
                        if (1 == value) {
                            mD.dispose();
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        KLog.d("e:" + e.toString());
                    }

                    @Override
                    public void onComplete() {
                        KLog.d("onComplete");
                    }
                });
                
                

按照自上而下的顺序,开始吧

Observable.create(ObservableOnSubscribe<T> source)

   public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
    }

流程的第一步,创建了两个对象:ObservableOnSubscribe 和 ObservableCreate 。

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) {
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        observer.onSubscribe(parent);

        try {
            source.subscribe(parent);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
    }
    
    //省略其他代码
    
}

ObservableCreate 继承Observable,在构造函数中保存了上一级创建的 ObservableOnSubscribe 对象的引用。

public abstract class Observable<T> implements ObservableSource<T>{...}
public interface ObservableSource<T> {

    void subscribe(Observer<? super T> observer);
}

上面的2段源码清楚的看到,Observable 是一个抽象类,是 ObservableSource 的实现类,而 ObservableSource 类是一个接口,它表示事件源。内部只有一个方法 subscribe 该方法表示通过 Observer 订阅当前的事件源。那么事件发布的事件,在 Observer 订阅者中就会被收到。了解了 Observable 的顶层接口之后,我们就知道该体系最重要的一个功能那就是 subscribe 方法了,因此我们就重点关注子类的 subscribe 方法。

现在,把视角转到Observable的subscribe()方法来,看看它做了什么处理。

 public final void subscribe(Observer<? super T> observer) {
        ObjectHelper.requireNonNull(observer, "observer is null");
        try {
            observer = RxJavaPlugins.onSubscribe(this, observer);

            ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
            //这段代码是核心代码
            subscribeActual(observer);
        } catch (NullPointerException e) { // NOPMD
            throw e;
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            // can't call onError because no way to know if a Disposable has been set or not
            // can't call onSubscribe because the call might have set a Subscription already
            RxJavaPlugins.onError(e);

            NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
            npe.initCause(e);
            throw npe;
        }
    }
    
    
     protected abstract void subscribeActual(Observer<? super T> observer);

他把observer订阅者传递给subscribeActual(Observer observer)抽象方法,这意味着所有Observable的子类,我们只要关心 subscribeActual(observer); 这个方法就好的。

好的,那么我们就回到最开始的ObservableCreate,去看看他在subscribeActual()做了什么

   @Override
    protected void subscribeActual(Observer<? super T> observer) {
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        observer.onSubscribe(parent);

        try {
            source.subscribe(parent);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
    }

在上面的代码里面,先是创建了一个发射器CreateEmitter,然后回调给 observer#onSubscribe() ,最后是通知上一级的Observable(也就是代码里的source)你可以发送事件了。这边不太了解RxJava可能有疑问我为什么这么下定论?因为事件是在被观察者“订阅”观察者时后才发送的!!!

subscribeOn(Schedulers.io())

这个方法的作用是让上游事件切换线程的,不管它在整个流中使用了几次,只有第一次是有效的。why? 先把这个疑问放下,后面看看流程图就应该明白了。

  public final Observable<T> subscribeOn(Scheduler scheduler) {
        ObjectHelper.requireNonNull(scheduler, "scheduler is null");
        return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
    }
    

public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
    final Scheduler scheduler;

    public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
        super(source);
        this.scheduler = scheduler;
    }

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

        s.onSubscribe(parent);

        parent.setDisposable(scheduler.scheduleDirect(new Runnable() {
            @Override
            public void run() {
                source.subscribe(parent);
            }
        }));
    }
    //省略部分代码
    
}

是不是很熟悉,因为AbstractObservableWithUpstream也是继承自Observable。subscribeActual()方法里执行的也是相似的逻辑,只不过是多了scheduler线程相关的逻辑,这里先不进行详细分析。

abstract class AbstractObservableWithUpstream<T, U> extends Observable<U> implements HasUpstreamObservableSource<T> {

    /** The source consumable Observable. */
    protected final ObservableSource<T> source;

    /**
     * Constructs the ObservableSource with the given consumable.
     * @param source the consumable Observable
     */
    AbstractObservableWithUpstream(ObservableSource<T> source) {
        this.source = source;
    }

    @Override
    public final ObservableSource<T> source() {
        return source;
    }

}

这个抽象类也是保存了上一个Observable的引用。

observeOn(AndroidSchedulers.mainThread())

我猜这边应该是相似的代码。

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

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        if (scheduler instanceof TrampolineScheduler) {
            source.subscribe(observer);
        } else {
            Scheduler.Worker w = scheduler.createWorker();

            source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
        }
    }
    
    //省略相关代码
}

果不其然,就不赘述了。

subscribe(Observer observer)

subscribe后,被观察者(Observable)一旦有发射什么事件,观察者(Observer)都可以接收事件。

总结

过程:断点调试,绘制流程图

[图片上传失败...(image-cd3051-1524734258521)]

还记得在介绍 #subscribeOn(Schedule)方法提出的那个问题?

无论我们在整个上游的事件流中使用了多少次#subscribeOn(Schedule)变换线程,只有第一次设置的有效。看了上面的流程图,相信应该明白了吧。

怎么进行线程切换的

subscribeOn(Schedulers.io())

首先了解下Scheduler.io()方法,它返回的是一个Scheduler,Scheduler是一个抽象方法,我们知道抽象方法是不能被实例化的,那么返回的肯定是它的实现类:

   public static Scheduler io() {
        return RxJavaPlugins.onIoScheduler(IO);
    }

上面代码里的IO对象是什么呢?

  IO = RxJavaPlugins.initIoScheduler(new Callable<Scheduler>() {
        @Override
        public Scheduler call() throws Exception {
            return IoHolder.DEFAULT;
        }
    });
    
    static final class IoHolder {
        static final Scheduler DEFAULT = new IoScheduler();
    }

答案是IoScheduler对象。

在前面的学习中,我们知道了subscribeOn(Schedulers.io())返回的对象是ObservableSubscribeOb对象


    public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
        super(source);
        this.scheduler = scheduler;
    }

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

        s.onSubscribe(parent);

        parent.setDisposable(scheduler.scheduleDirect(new Runnable() {
            @Override
            public void run() {
                source.subscribe(parent);
            }
        }));
    }

source.subscribe(parent) 被放在一个Runnable中执行,那么他是否已经就在子线程执行了呢?

NO,NO,NO,这还得看Runnable是被放在哪个线程上的,说不定是mainThread呢。

先看看scheduleDirect方法

  //无延迟执行
  public Disposable scheduleDirect(Runnable run) {
        return scheduleDirect(run, 0L, TimeUnit.NANOSECONDS);
    }

scheduleDirect.java

 public Disposable scheduleDirect(Runnable run, long delay, TimeUnit unit) {
        //createWorker是一个抽象方法,创建一个可以可以执行 run 的 worker 
        final Worker w = createWorker();
        //对 run 进行了包装,实际上还是 run 这个对象
        final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
        //decoratedRun 交给了 worker 去执行
        w.schedule(new Runnable() {
            @Override
            public void run() {
                try {
                    decoratedRun.run();
                } finally {
                    w.dispose();
                }
            }
        }, delay, unit);

        return w;
    }

直指IoScheduler#createWorker()

    @Override
    public Worker createWorker() {
        return new EventLoopWorker(pool.get());
    }

EventLoopWorker.java

 static final class EventLoopWorker extends Scheduler.Worker {
        //省略部分code

        @Override
        public Disposable schedule(Runnable action, long delayTime, TimeUnit unit) {
            if (tasks.isDisposed()) {
                // don't schedule, we are unsubscribed
                return EmptyDisposable.INSTANCE;
            }

            return threadWorker.scheduleActual(action, delayTime, unit, tasks);
        }
    }

EventLoopWorker extends Scheduler.Worker ,Worker这个抽象类有个schedule()抽象方法需要重写,所以这个类的核心逻辑就在schedule()方法里:==threadWorker.scheduleActual(action, delayTime, unit, tasks);== ,点击进去看看:

public class NewThreadWorker extends Scheduler.Worker implements Disposable {
    //executor  是一个线程池
    private final ScheduledExecutorService executor;
    
    volatile boolean disposed;

    public NewThreadWorker(ThreadFactory threadFactory) {
        executor = SchedulerPoolFactory.create(threadFactory);
    }
    
    //省略部分代码
    
    public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, TimeUnit unit, DisposableContainer parent) {
            //对传进来的run进行包装
            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) {
                    f = executor.submit((Callable<Object>)sr);
                } else {
                    f = executor.schedule((Callable<Object>)sr, delayTime, unit);
                }
                
                //拿到f,传给ScheduledRunnable
                sr.setFuture(f);
            } catch (RejectedExecutionException ex) {
                parent.remove(sr);
                RxJavaPlugins.onError(ex);
            }
    
            return sr;
        }

ScheduledRunnable里面又做了什么?

  @Override
    public void run() {
        try {
            try {
                //actual就是通过构造函数传递进来的Runnable
                actual.run();
            } catch (Throwable e) {
                // Exceptions.throwIfFatal(e); nowhere to go
                RxJavaPlugins.onError(e);
            }
        } finally {
            Object o = get(PARENT_INDEX);
            if (o != DISPOSED && o != null && compareAndSet(PARENT_INDEX, o, DONE)) {
                ((DisposableContainer)o).delete(this);
            }

            for (;;) {
                o = get(FUTURE_INDEX);
                if (o == DISPOSED || compareAndSet(FUTURE_INDEX, o, DONE)) {
                    break;
                }
            }
        }
    }

“故事”的最终还是交给actual.run()去执行,也就是执行==source.subscribe(parent);== 几经“旋转跳跃”,它投入了子线程的怀抱。

小结

切换到子线程的逻辑还是比较容易的,利用线程池而已....

observeOn(AndroidSchedulers.mainThread())

首先了解下AndroidSchedulers.mainThread()

    /** A {@link Scheduler} which executes actions on the Android main thread. */
    public static Scheduler mainThread() {
        return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);
    }
    
    
    private static final Scheduler MAIN_THREAD = RxAndroidPlugins.initMainThreadScheduler(
            new Callable<Scheduler>() {
                @Override public Scheduler call() throws Exception {
                    return MainHolder.DEFAULT;
                }
            });
    
    private static final class MainHolder {

        static final Scheduler DEFAULT = new HandlerScheduler(new Handler(Looper.getMainLooper()));
    }

  

可以清楚的知道AndroidSchedulers.mainThread()返回的Schedule类是HandlerScheduler,内持有一个可以在主线程发送消息的handler对象。

接下来将代码定位到ObservableObserveOn#subscribeActual()方法

 protected void subscribeActual(Observer<? super T> observer) {
        //TrampolineScheduler是在当前线程执行的,但不是立即执行,需要等当前的工作单元都执行结束后。
        if (scheduler instanceof TrampolineScheduler) {
            source.subscribe(observer);
        } else {
            //这个schedule是HandlerScheduler,创建了一个 Scheduler.Worker
            Scheduler.Worker w = scheduler.createWorker();

            source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
        }
    }
ObserveOnObserver
@Override
public void onNext(T t) {
    if (done) {
        return;
    }
    
    if (sourceMode != QueueDisposable.ASYNC) {
        queue.offer(t);
    }
    
    //划重点!
    schedule();
}
void schedule() {
    if (getAndIncrement() == 0) {
        worker.schedule(this);
    }
}

==getAndIncrement() == 0== 是校验没有原子性,没有多个任务在同时执行

scheduler.createWorker()做了什么?

HandlerScheduler
 @Override
    public Worker createWorker() {
        return new HandlerWorker(handler);
    }

    private static final class HandlerWorker extends Worker {
        private final Handler handler;

        private volatile boolean disposed;

        HandlerWorker(Handler handler) {
            this.handler = handler;
        }

        @Override
        public Disposable schedule(Runnable run, long delay, TimeUnit unit) {
            if (run == null) throw new NullPointerException("run == null");
            if (unit == null) throw new NullPointerException("unit == null");

            if (disposed) {
                return Disposables.disposed();
            }

            run = RxJavaPlugins.onSchedule(run);

            ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);

            Message message = Message.obtain(handler, scheduled);
            message.obj = this; // Used as token for batch disposal of this worker's runnables.

            handler.sendMessageDelayed(message, Math.max(0L, unit.toMillis(delay)));

            // Re-check disposed state for removing in case we were racing a call to dispose().
            if (disposed) {
                handler.removeCallbacks(scheduled);
                return Disposables.disposed();
            }

            return scheduled;
        }
        
        //省略部分代码

    }

在HandlerWorker#schedule()方法里通过Handler发送Message,Message中的callback对应run对象。

我们都知道Handler发送消息后会在dispatchMessage()方法处理

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}



private static void handleCallback(Message message) {
    message.callback.run();
}

清楚的看到了业务逻辑执行==message.callback.run();== 也就是说ScheduledRunnable会被执行,ScheduledRunnable是ObserveOnObserver#schedule()方法里被传入的。

 void schedule() {
    if (getAndIncrement() == 0) {
        worker.schedule(this);
    }
 }

它传入的是this,那么最终执行的是ObserveOnObserver#run()方法了。

   @Override
    public void run() {
        //outputFused默认值为false
        if (outputFused) {
            drainFused();
        } else {
            drainNormal();
        }
    }
 void drainNormal() {
            int missed = 1;

            final SimpleQueue<T> q = queue;
            final Observer<? super T> a = actual;

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

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

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

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

                    if (empty) {
                        break;
                    }

                    a.onNext(v);
                }

                missed = addAndGet(-missed);
                if (missed == 0) {
                    break;
                }
            }
        }

自上而下看了过来,找到了 ==a.onNext(v);== ,记住它现在所在的是主线程。

小结
  • 1、==AndroidSchedulers.MainThread()==,这个Scheduler(HandlerScheduler)它持有在主线程执行的Handle。
  • 2、ObserveOn返回的对象是==ObservableObserveOn==,封装了一个持有原观察者的Observer(ObserveOnObserver),它实现了Runnable接口,当执行到onNext()时,执行了Scheduler.Worker#schedule(Runnable)方法,并把this传递进去了。
  • HandlerScheduler.HandlerWorker#schedule()方法里用handle发送Message,而这个Message的callback就是之前传递进来的this(Runnable),最终在dispathMessage()方法里得到了执行,也就是执行run方法。回调到ObservableObserveOn.Observer#run()方法执行actual.onNext(),因为handle所在的线程是主线程,所以onNext(T t)所在的线程也是主线程。

一句话总结RxJava子线程和主线程的原理

切换到子线程的关键是将Runnable放到线程池去执行,切换到主线程是利用在主线程实例化的Handle发送Message,让runnable回调到主线程去。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,277评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,777评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,946评论 0 245
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,271评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,636评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,767评论 1 221
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,989评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,733评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,457评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,674评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,155评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,518评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,160评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,114评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,898评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,822评论 2 280
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,705评论 2 273

推荐阅读更多精彩内容

  • 我从去年开始使用 RxJava ,到现在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的...
    Jason_andy阅读 5,384评论 7 62
  • 转一篇文章 原地址:http://gank.io/post/560e15be2dca930e00da1083 前言...
    jack_hong阅读 883评论 0 2
  • 前言我从去年开始使用 RxJava ,到现在一年多了。今年加入了 Flipboard 后,看到 Flipboard...
    占导zqq阅读 9,125评论 6 151
  • 经过一周的朗读和背诵,总体感觉不错,说实话因为最近工作忙 的原因,有些天的刻意练习的时间是 不足的,而我通过自己的...
    Explorer84阅读 265评论 0 0
  • 流程控制语句 if if语句是编程语言最常用的语句,语法 其中condition可以是任意表达式,结果不一定是布尔...
    卓小生阅读 160评论 0 0