RxJava源碼分析之線程調(diào)度(二)

在上一篇文章當(dāng)中我們把RxJava的上游線程切換的源碼都大致梳理了一遍,如果還沒(méi)有看的請(qǐng)猛戳這里,但是光有上游的線程切換是不足以讓我們完成在實(shí)際項(xiàng)目中的應(yīng)用的,絕大多數(shù)時(shí)候我們都需要在下游進(jìn)行線程的切換來(lái)處理上游在其他線程中得到的結(jié)果。所以現(xiàn)在我們就來(lái)分析一下RxJava源碼中是如何實(shí)現(xiàn)對(duì)下游線程的切換控制管理的。

這里我們一切換到Android主線程為例:

.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

現(xiàn)在就從observeOn(AndroidSchedulers.mainThread())入手,探探究竟。
首先我們來(lái)看一下RxJava是如何得到一個(gè)Android主線程的Scheduler的即HandlerScheduler。我們點(diǎn)進(jìn)源碼看一下:

/** Android-specific Schedulers. */
public final class AndroidSchedulers {

    private static final class MainHolder {
        //創(chuàng)建一個(gè)Handle拿到主線程的Looper 創(chuàng)建默認(rèn)的 HandlerScheduler
        static final Scheduler DEFAULT = new HandlerScheduler(new Handler(Looper.getMainLooper()));
    }

    private static final Scheduler MAIN_THREAD = RxAndroidPlugins.initMainThreadScheduler(
            new Callable<Scheduler>() {
                @Override public Scheduler call() throws Exception {
                    //該Callable默認(rèn)返回的就是上面的HandleScheduler
                    return MainHolder.DEFAULT;
                }
            });

    /** A {@link Scheduler} which executes actions on the Android main thread. */
    public static Scheduler mainThread() {
        //這里就是入口 可以看到其實(shí)該方法是直接獲取到了一個(gè)靜態(tài)的Scheduler常量。
        return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);
    }

    /** A {@link Scheduler} which executes actions on {@code looper}. */
    public static Scheduler from(Looper looper) {
        if (looper == null) throw new NullPointerException("looper == null");
        return new HandlerScheduler(new Handler(looper));
    }

    private AndroidSchedulers() {
        throw new AssertionError("No instances.");
    }
}

好了現(xiàn)在Scheduler有了,我們繼續(xù)分析observeOn方法。

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

看到了吧,RxJava所有的代碼基本都是一致的,橋接模式,這里看到是創(chuàng)建了一個(gè)ObservableObserveOn對(duì)象,當(dāng)然第二個(gè)參數(shù)默認(rèn)是false,表明了如果執(zhí)行了onError() 將會(huì)重新發(fā)送一遍上游的事件序列,第三個(gè)參數(shù)是緩存的大小默認(rèn)是128。我們點(diǎn)進(jìn)ObservableObserveOn的構(gòu)造方法看看里面都做了什么,很關(guān)鍵。

//可以看到套路基本都是一樣的, ObservableObserveOn<T> 同樣是繼承于AbstractObservableWithUpstream<T, T> ,用來(lái)保存上游的原事件流。
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;
    }
//訂閱的真正發(fā)生之處
    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        if (scheduler instanceof TrampolineScheduler) {//肯定不是這個(gè)Scheduler啊,我們這里是HandleScheduler
            source.subscribe(observer);
        } else {
            //創(chuàng)建HandlerScheduler的Worker,HandlerWorker.
            Scheduler.Worker w = scheduler.createWorker();
            //上游事件和下游事件產(chǎn)生訂閱,這里又是一個(gè)包裝類ObserveOnObserver包裝了下游真正的Observer。
           //我們到ObserverOnObserver里面去看看,其是一個(gè)靜態(tài)內(nèi)部類
          //這里是把worker,delayError,bufferSizew也都傳了進(jìn)去
            source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
        }
    }
  //實(shí)現(xiàn)了Runnable接口,繼承于BasicIntQueueDisposable
    static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T>
    implements Observer<T>, Runnable {

        private static final long serialVersionUID = 6576896619930983584L;
        final Observer<? super T> actual;
        final Scheduler.Worker worker;
        final boolean delayError;
        final int bufferSize;

        SimpleQueue<T> queue;

        Disposable s;

        Throwable error;
        volatile boolean done;

        volatile boolean cancelled;

        int sourceMode;

        boolean outputFused;

        ObserveOnObserver(Observer<? super T> actual, Scheduler.Worker worker, boolean delayError, int bufferSize) {
            this.actual = actual;
            this.worker = worker;
            this.delayError = delayError;
            this.bufferSize = bufferSize;
        }

        @Override
        public void onSubscribe(Disposable s) {
            if (DisposableHelper.validate(this.s, s)) {
                this.s = s;
                if (s instanceof QueueDisposable) {
                    @SuppressWarnings("unchecked")
                    QueueDisposable<T> qd = (QueueDisposable<T>) s;

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

                    if (m == QueueDisposable.SYNC) {
                        sourceMode = m;
                        queue = qd;
                        done = true;
                        actual.onSubscribe(this);
                        schedule();
                        return;
                    }
                    if (m == QueueDisposable.ASYNC) {
                        sourceMode = m;
                        queue = qd;
                        actual.onSubscribe(this);
                        return;
                    }
                }
              //事件的緩存隊(duì)列 確定了緩存隊(duì)列的大小
                queue = new SpscLinkedArrayQueue<T>(bufferSize);
              //執(zhí)行真正的onSubscribe方法
                actual.onSubscribe(this);
            }
        }

        @Override
        public void onNext(T t) {
            if (done) {
                return;
            }

            if (sourceMode != QueueDisposable.ASYNC) {
                queue.offer(t);
            }
         //開始調(diào)度    
        schedule();
        }

        @Override
        public void onError(Throwable t) {
            if (done) {
                RxJavaPlugins.onError(t);
                return;
            }
            error = t;
            done = true;
             //開始調(diào)度 
            schedule();
        }

        @Override
        public void onComplete() {
            if (done) {
                return;
            }
            done = true;//已經(jīng)完成
            //開始調(diào)度  
            schedule();
        }
      //取消訂閱
        @Override
        public void dispose() {
            if (!cancelled) {
                cancelled = true;
                s.dispose();
                worker.dispose();
                if (getAndIncrement() == 0) {
                    queue.clear();
                }
            }
        }
      //判斷是否被取消訂閱
        @Override
        public boolean isDisposed() {
            return cancelled;
        }
      //執(zhí)行調(diào)度的方法 
        void schedule() {
            if (getAndIncrement() == 0) {
              //傳入當(dāng)前ObserveOnObserver對(duì)象,其實(shí)現(xiàn)了Runnable接口
                worker.schedule(this);
            }
        }
      
        void drainNormal() {
            int missed = 1;
            //緩存數(shù)據(jù)的隊(duì)列
            final SimpleQueue<T> q = queue;
            //實(shí)際下游的Observer
            final Observer<? super T> a = actual;

            for (;;) {
                //檢測(cè)事件是否被終止,如果終止了直接跳出循環(huán)
                if (checkTerminated(done, q.isEmpty(), a)) {
                    return;
                }

                for (;;) {
                    //標(biāo)記事件是否完成
                    boolean d = done;
                    T v;

                    try {
                        //拿到隊(duì)列里的第一個(gè)事件
                        v = q.poll();
                    } catch (Throwable ex) {
                        //發(fā)生異常了 做一系列的后續(xù)動(dòng)作
                        //取消訂閱,隊(duì)列的制空,發(fā)送異常事件,取消線程調(diào)度,最后跳出循環(huán)
                        Exceptions.throwIfFatal(ex);
                        s.dispose();
                        q.clear();
                        a.onError(ex);
                        worker.dispose();
                        return;
                    }
                    //判斷事件是否為空
                    boolean empty = v == null;

                    if (checkTerminated(d, empty, a)) {
                        return;
                    }
                    //為空直接進(jìn)入下一輪循環(huán)
                    //因?yàn)樯嫌蔚氖录幚硪彩切枰獣r(shí)間的,上游的執(zhí)行有可能是非常大量的數(shù)據(jù)所以可能會(huì)出現(xiàn)緩存隊(duì)列里面暫時(shí)沒(méi)有事件,所以這里需要一直進(jìn)行循環(huán)去等待新的事件產(chǎn)生
                    if (empty) {
                        break;
                    }
                    //發(fā)送事件
                    a.onNext(v);
                }
              //下面這段代碼我也不是很確定他的意思,這里我說(shuō)一下我自己的理解不知道正不正確:
              //因?yàn)镺bserveOnObserver是繼承于BasicIntQueueDisposable ,而BasicIntQueueDisposable 又繼承了AtomicInteger,一個(gè)原子操作類
            //用一個(gè)Integer整數(shù)來(lái)控制當(dāng)前ObserveOnObserver對(duì)象的并發(fā)操作
            //如果當(dāng)前ObserveOnObserver對(duì)象沒(méi)有被其他線程獨(dú)占,那么該對(duì)象就自己持有的話(代表已經(jīng)執(zhí)行完了當(dāng)前的事件),就可以執(zhí)行addAndGet(int i)方法了。
            //執(zhí)行完改方法對(duì)自己的負(fù)數(shù)相加那么最終得出的是0,為0的話就可以開始下一個(gè)循環(huán)了,那么以后的每一個(gè)循環(huán)missed的值都為0都可以直接break!
            //最終要的是addAndGet()是一個(gè)阻塞式的方法,如果不成功的話,它會(huì)重新執(zhí)行一遍
          //所以我分析得出這里其實(shí)是一個(gè)控制標(biāo)記位“好了!現(xiàn)在輪到你了,開始吧”當(dāng)?shù)谝淮文玫綑?quán)限后就可以一直執(zhí)行下去了。
        
                missed = addAndGet(-missed);
                if (missed == 0) {
                    break;
                }
            }
        }

        void drainFused() {
   ...........
        }
        //具體的run方法內(nèi)部
        @Override
        public void run() {
            if (outputFused) {
                drainFused();
            } else {
                //去處理隊(duì)列里面緩存的數(shù)據(jù)
                drainNormal();
            }
        }
        //檢查是否終止  代碼都很簡(jiǎn)單 我就不做注釋了
        boolean checkTerminated(boolean d, boolean empty, Observer<? super T> a) {
            if (cancelled) {
                queue.clear();
                return true;
            }
            if (d) {
                Throwable e = error;
                if (delayError) {
                    if (empty) {
                        if (e != null) {
                            a.onError(e);
                        } else {
                            a.onComplete();
                        }
                        worker.dispose();
                        return true;
                    }
                } else {
                    if (e != null) {
                        queue.clear();
                        a.onError(e);
                        worker.dispose();
                        return true;
                    } else
                    if (empty) {
                        a.onComplete();
                        worker.dispose();
                        return true;
                    }
                }
            }
            return false;
        }
    }
}

同樣是裝飾模式,關(guān)鍵就是每當(dāng)執(zhí)行onNext(),onError(),onCompleted()方法的時(shí)候,都會(huì)開啟線程的調(diào)度,上游的每一次事件,都會(huì)在指定線程中處理,這就是核心。然后就執(zhí)行了具體的Worker實(shí)現(xiàn)類里面的schedule方法,我們一起看一下。

//HandlerWorker里面的schedule方法,其第二個(gè)參數(shù)為0L,第三個(gè)參數(shù)為TimeUnit.NANOSECONDS。
 @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();
            }
            //滿篇飛的Hook函數(shù) +_+
            run = RxJavaPlugins.onSchedule(run);
            //封裝當(dāng)前持有主線程Looper的handler和ObserveOnObserver對(duì)象
            ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);
            //創(chuàng)建Message
            Message message = Message.obtain(handler, scheduled);
            message.obj = this; // Used as token for batch disposal of this worker's runnables.
            //給主線程發(fā)送消息
            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) {
            //如果取消訂閱了 就remove掉消息處理的回調(diào)接口
                handler.removeCallbacks(scheduled);
                return Disposables.disposed();
            }

            return scheduled;
        }

當(dāng)然了最后主線程的執(zhí)行的程序是ScheduledRunnable里面的run()方法,代碼如下:

 @Override
        public void run() {
            try {
              //ObserveOnObserver對(duì)象的run方法
                delegate.run();
            } catch (Throwable t) {
                //捕獲異常了進(jìn)行一系列處理
                IllegalStateException ie =
                    new IllegalStateException("Fatal Exception thrown on Scheduler.", t);
                RxJavaPlugins.onError(ie);
                Thread thread = Thread.currentThread();
                thread.getUncaughtExceptionHandler().uncaughtException(thread, ie);
            }
        }

這樣RxJava就實(shí)現(xiàn)了把上游發(fā)送的每一個(gè)事件都巧妙地轉(zhuǎn)換到了指定線程中處理,此處是Android主線程。
可以看到如果你在下游多次調(diào)用observeon()的話線程是會(huì)一直切換的,這也是網(wǎng)上一直說(shuō)的結(jié)論。每一次切換線程,都會(huì)把對(duì)應(yīng)的Observer對(duì)象的各項(xiàng)處理方法的處理執(zhí)行在制定線程當(dāng)中。
大概瀏覽完源碼你會(huì)發(fā)現(xiàn),RxJava的設(shè)計(jì)者真的是把面向?qū)ο蟮乃枷胗玫搅藰O致,抽象接口與實(shí)體,設(shè)計(jì)模式地巧用都無(wú)處不在,感嘆自己要學(xué)的真的還有太多,如果讓我來(lái)寫不知道還要多少年才能寫出如此牛B的代碼。
這也算是我第一次寫源碼分析的文章,還有很多地方有待提高,最開始聽說(shuō)別人源碼分析很重要,不光要會(huì)用那些優(yōu)秀的Library更要理解其中的精髓,與是我傻乎乎地悶著腦袋去看,結(jié)果真的看不懂,后來(lái)看了一本書叫做《Android源碼設(shè)計(jì)模式》才恍然大悟,設(shè)計(jì)模式地巧用在各大優(yōu)秀的開源Library中無(wú)處不在,只有真正地理解了設(shè)計(jì)模式,精通架構(gòu),才能寫出如此優(yōu)秀的代碼。最后再安利一本書《設(shè)計(jì)模式之禪》這本書很有意思,作者語(yǔ)言幽默風(fēng)趣,像看連環(huán)畫一樣很有意思。
哈哈 廢話說(shuō)了一大堆了,如果上面我的分析有誤的話,歡迎指正批評(píng),有什么不懂得地方也可以一起探討。

最后

沒(méi)有最后了,大家再見~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,885評(píng)論 6 541
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,312評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,993評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,667評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,410評(píng)論 6 411
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,778評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,775評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,955評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,521評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,266評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,468評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,998評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,696評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,095評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,385評(píng)論 1 294
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,193評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,431評(píng)論 2 378

推薦閱讀更多精彩內(nèi)容