友好 RxJava2.x 原始碼解析(二)執行緒切換

jokermonn發表於2017-12-03

系列文章:

本文 csdn 地址:友好 RxJava2.x 原始碼解析(二)執行緒切換

本文基於 RxJava 2.1.3

前言

本文基於讀者會使用 RxJava 2.x 而講解,基本原理不涉及,示例只純粹為示例而示例。

示例程式碼

示例原始碼:
Observable
        .create(new ObservableOnSubscribe<String>() {
            @Override
                public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                    Log.e("TAG", "subscribe(): 所線上程為 " + Thread.currentThread().getName());
                    emitter.onNext("1");
                    emitter.onComplete();
                }
            })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
                Log.e("TAG", "onSubscribe(): 所線上程為 " + Thread.currentThread().getName());
            }

            @Override
            public void onNext(String s) {
                Log.e("TAG", "onNext(): 所線上程為 " + Thread.currentThread().getName());
            }

            @Override
            public void onError(Throwable e) {
            }

            @Override
            public void onComplete() {
                Log.e("TAG", "onComplete(): 所線上程為 " + Thread.currentThread().getName());
            }
        });
複製程式碼

輸出結果:

E/TAG: onSubscribe(): 所線上程為 main
E/TAG: subscribe(): 所線上程為 RxCachedThreadScheduler-1
E/TAG: onNext(): 所線上程為 main
E/TAG: onComplete(): 所線上程為 main
複製程式碼

原始碼解析

我們可以發現,除了 Observable 的 subscribe(ObservableEmitter) 方法執行在 io 執行緒,Observer 的方法都是執行在 main 執行緒的,接下來就請各位讀者跟著筆者來分析了。

Observer#onSubscribe(Dispose)

看到標題部分讀者就疑惑了,明明是說執行緒切換,跟 Observer#onSubscribe() 方法有什麼關係呢?前方的 log 中展示 Observer#onSubscribe() 方法在主執行緒執行的,但是這個主執行緒是由 .observeOn(AndroidSchedulers.mainThread()) 所導致的嗎?為了解決這個疑惑,我們可以在外面套一個子執行緒,然後去執行該邏輯,程式碼如下:

new Thread() {
    @Override
    public void run() {
	    Log.e("TAG", "run: 所線上程為 " + Thread.currentThread().getName());
        // 新增示例程式碼
    }
}.start();
複製程式碼

列印結果:

run: 所線上程為 Thread-554
onSubscribe(): 所線上程為 Thread-554
subscribe(): 所線上程為 RxCachedThreadScheduler-1
onNext(): 所線上程為 main
onComplete(): 所線上程為 main
複製程式碼

所以實際上 Observer#onSubscribe() 的執行執行緒是當前執行緒,它並不受 subscribe(Scheduler)observeOn(Scheduler) 所影響(因為筆者這段程式碼寫在了 Android 主執行緒當中,所以當前執行緒是主執行緒)。本文不在此擴充套件原因,具體原始碼追溯和檢視前一篇文章,簡而言之—— subscribe(Observer) -> subscribeActual(Observer) -> Observer#onSubscribe(),我們可以看到 subscribe(Observer) 的執行執行緒是當前執行緒,而在上面所述的資料流中也不存在資料切換的過程,所以 onSubscribe() 執行的執行緒也是當前執行緒。

Observable#observeOn(Scheduler)

此小節針對 Observable#observeOn(Scheduler) 講解,所以將示例程式碼更改如下:

new Thread() {
    @Override
    public void run() {
        Log.e("TAG", "run: 當前預設執行環境為 " + Thread.currentThread().getName());
        Observable
            .create(new ObservableOnSubscribe<String>() {
                @Override
                public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                    emitter.onNext("1");
                }
            })
            // 僅保留 observeOn(Scheduler)
            .observeOn(Schedulers.io())
            .subscribe(new Observer<String>() {
                @Override
                public void onSubscribe(Disposable d) {
                }

                @Override
                public void onNext(String s) {
                    Log.e("TAG", "onNext(): 所線上程為 " + Thread.currentThread().getName());
                }

                @Override
                public void onError(Throwable e) {
                }

                @Override
                public void onComplete() {
                }
            });
    }
} .start();
複製程式碼

輸出結果:

E/TAG: run: 當前預設執行執行緒為 Thread-610
E/TAG: onNext(): 所線上程為 RxCachedThreadScheduler-1
複製程式碼

不作用上游 Observable

同樣的,直接先進入 Observable#observeOn(Scheduler) 原始碼檢視一下,發現其最終會呼叫 Observable#的observeOn(Scheduler, boolean, int) 方法,該方法將會返回一個 Observable 物件。那麼老問題來了,是哪個 Observable 物件呼叫的 observeOn() 方法,又返回了一個怎樣的 Observable 物件?

第一個問題很簡單,是 Observable.create(ObservableOnSubscribe) 物件返回的一個 Observable,而且這個 Observable 是一個 ObservableCreate 物件(這裡不理解的可以檢視第一篇文章)。但是 Observable#observeOn(Scheduler, boolean, int) 是沒有被任何子類重寫的,這意味著它的子類都是呼叫它的該方法。

第二個問題來了,返回了一個怎樣的 Observable 物件呢?實際上這裡的分析流程和第一篇文章中所闡述的流程是一模一樣的,我們戳進 Observable#observeOn(Scheduler, boolean, int) 原始碼,發現它最終會返回一個 new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize) 物件,這裡我們只關注前兩個物件,第一個引數 this 是指上游的 Observable 物件,也就是我們第一個問題中所涉及到的 Observable 物件,第二個引數 scheduler 毋庸置疑就是我們所傳入的 Scheduler 物件了,在此也就是我們的 AndroidSchedulers.mainThread()

通過第一篇的學習,我們應該會輕車熟路地開啟 ObservableObserveOn 類並檢視它的核心 subscribeActual() 方法以及建構函式——

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) {
    // 如果傳入的 scheduler 是 Scheduler.trampoline() 的情況
    // 該執行緒的意義是傳入當前執行緒,也就是不做任何執行緒切換操作
    if (scheduler instanceof TrampolineScheduler) {
        source.subscribe(observer);
    } else {
        Scheduler.Worker w = scheduler.createWorker();
        source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
    }
}
複製程式碼

直接進入第二個 case,首先先略去第19行程式碼,看到第20行程式碼,source(上游 Observable) 和 Observable#subscribe() 操作都沒有任何變化,唯一改變的地方就是將 Observer 進行了封裝,所以我們可以因此得出結論, Observable#observeOn(Scheduler) 並不會對上游執行緒執行環境有任何影響。(如果看到這裡不能夠理解的話,後文中會有通俗易懂的虛擬碼輔助理解)

作用下游 Observer

經過上文友好 RxJava2.x 原始碼解析(一)基本訂閱流程一文的分析我們知道 ObservableEmitter 的 onNext(T) 方法會觸發「下游」 Observer 的 onNext(T) 方法,而此時的「下游」 Observer 物件是經過 Observable#observeOn(Scheduler) 封裝的 ObserveOnObserver 物件,所以我們不妨開啟 ObserveOnObserver 的 onNext(T) 方法——

@Override
public void onNext(T t) {
    // 刪除無關原始碼
    queue.offer(t);
    schedule();
}
複製程式碼

可以看到 onNext(T) 方法做了兩件事——一是將當前方法傳入的物件新增進佇列;另一是執行 schedule() 方法,開啟 schedule() 方法原始碼——

void schedule() {
    // 刪除無關原始碼
    worker.schedule(this);
}
複製程式碼

所以將會執行 worker.schedule(Runnable),可向下繼續追溯到 schedule(Runnable, long, TimeUnit ) ,該方法是一個抽象方法,所以我們可以想到,排程器們就是通過實現該方法來建立各色各樣的執行緒的。所以我們繼續追溯到 IoScheduler 的 schedule(Runnable, long, TimeUnit) 中,原始碼如下:

    public Disposable schedule(@NonNull Runnable action, long delayTime, @NonNull TimeUnit unit) {
        // 刪除無關原始碼
        return threadWorker.scheduleActual(action, delayTime, unit, tasks);
    }
複製程式碼

繼續追溯下去——

@NonNull
public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
    Future<?> f;
    if (delayTime <= 0) {
        f = executor.submit((Callable<Object>)sr);
    } else {
        f = executor.schedule((Callable<Object>)sr, delayTime, unit);
    }
    sr.setFuture(f);

    return sr;
}
複製程式碼

executor 是一個 ScheduledExecutorService 物件,而 ScheduledExecutorService 的父介面是我們所熟悉的 ExecutorService 介面,所以很清晰 ScheduledExecutorService 具有建立和排程執行緒的能力,而其具體的實現在此就不討論了。

最後,我們不妨將上述所提到的幾段原始碼整體抽象結合一下:

@Override
public void onNext(T t) {
    // 刪除無關原始碼
    if (delayTime <= 0) {
        f = executor.submit((Callable<Object>)this);
    } else {
        f = executor.schedule((Callable<Object>)this, delayTime, unit);
    }
}
複製程式碼

總結一下:onNext(T) 方法會觸發 Scheduler 物件的 schedule(Runnable, long, TimeUnit) ,該方法是一個抽象方法,由子類實現,所以才有了多元多樣的 Schedulers.io()/Schedulers.computation()/Schedulers.trampoline() 等排程器,具體排程器的內部會使用相關的執行緒來 submit() 或者 schedule() 任務。解決完排程器的問題,那麼接下來就是看看 Runnable#run() 裡面的邏輯是什麼樣的,回到 ObserveOnObserver 中——

@Override
public void run() {
    drainNormal();
}
複製程式碼

drainNormal() 原始碼如下:

void drainNormal() {
    final SimpleQueue<T> q = queue;
    final Observer<? super T> a = actual;

    for (;;) {
        T v;

        try {
            v = q.poll();
        } catch (Throwable ex) {
        }
        boolean empty = v == null;

        if (empty) {
            break;
        }

        a.onNext(v);
    }
}
複製程式碼

可以看到實際上最後一行執行了 Observer#onNext(T) 方法,也就是意味著「ObserveOnObserver 中觸發下一層 Observer 的 onNext(T) 操作」在指定執行緒執行,也就達到了切換執行緒的目的了。

來個複雜的例子——

示例圖

經過友好 RxJava2.x 原始碼解析(一)基本訂閱流程一文我們知道,Observer 的傳遞是由下往上的,從源頭開始,我們自定義的 Observer 向上傳遞的時候到達第六個 Observable 的時候被執行緒封裝了一層,我們不妨使用虛擬碼演示一下——

public class Observer {
    Observer oldObserver;

    public Observer(Observer observer) {
        oldObserver = observer;
    }

    public void onNext(T t) {
        // 一些其他操作
        new Thread("Android mainThread") {
            @Override
            public void run() {
                oldObserver.onNext(t);
            }
        } .start();
    }

    public void onError(Throwable e) {
        // 一些其他操作
        new Thread("Android mainThread") {
            @Override
            public void run() {
                oldObserver.onError(e);
            }
        } .start();
    }

    public void onComplete() {
        // 一些其他操作
        new Thread("Android mainThread") {
            @Override
            public void run() {
                oldObserver.onComplete();
            }
        } .start();
    }
}
複製程式碼

Observer 繼續向上被傳遞,Observable#map() 中並未對 Observer 進行執行緒切換;再向上走,到達第四個 observeOn(Scheduler) 的時候,被 computation 執行緒巢狀了一層——

public class Observer {
    Observer oldObserver;

    public Observer(Observer observer) {
        oldObserver = observer;
    }

    public void onNext(T t) {
        // 一些其他操作
        new Thread("computation") {
            @Override
            public void run() {
                oldObserver.onNext(t);
            }
        } .start();
    }

    public void onError(Throwable e) {
        // 一些其他操作
        new Thread("computation") {
            @Override
            public void run() {
                oldObserver.onError(e);
            }
        } .start();
    }

    public void onComplete() {
        // 一些其他操作
        new Thread("computation") {
            @Override
            public void run() {
                oldObserver.onComplete();
            }
        } .start();
    }
}
複製程式碼

當然,繼續向上直到頂端 Observable——

public class Observer {
    Observer oldObserver;

    public Observer(Observer observer) {
        oldObserver = observer;
    }

    public void onNext(T t) {
        // 一些其他操作
        new Thread("io") {
            @Override
            public void run() {
                oldObserver.onNext(t);
            }
        } .start();
    }

    public void onError(Throwable e) {
        // 一些其他操作
        new Thread("io") {
            @Override
            public void run() {
                oldObserver.onError(e);
            }
        } .start();
    }

    public void onComplete() {
        // 一些其他操作
        new Thread("io") {
            @Override
            public void run() {
                oldObserver.onComplete();
            }
        } .start();
    }
}
複製程式碼

甚至更精簡的操作如下:

new Thread("Scheduler io") {
    @Override
    public void run() {
        // flatMap() 操作
        flatMap();
        System.out.println("flatMap 操作符執行執行緒:" + Thread.currentThread().getName());
        System.out.println("第二個 observeOn() 執行執行緒:" + Thread.currentThread().getName());
        // 第二個 observeOn() 操作
        new Thread("Scheduler computation") {
            @Override
            public void run() {
                // map() 操作
                map();
                System.out.println("map 操作符執行執行緒:" + Thread.currentThread().getName());
                System.out.println("第三個 observeOn() 執行執行緒:" + Thread.currentThread().getName());
                // 第三個 observeOn() 操作
                new Thread("Android mainThread") {
                    @Override
                    public void run() {
                        // Observer#onNext(T)/onComplete()/onError() 執行執行緒
                        System.out.println("Observer#onNext(T)/onComplete()/onError() 執行執行緒:" +
                                           Thread.currentThread().getName());
                    }
                } .start();
            }
        } .start();
    }
} .start();
複製程式碼

輸出結果:

flatMap 操作符執行執行緒:Scheduler io
第二個 observeOn() 執行執行緒:Scheduler io
map 操作符執行執行緒:Scheduler computation
第三個 observeOn() 執行執行緒:Scheduler computation
Observer#onNext(T)/onComplete()/onError() 執行執行緒:Android mainThread
複製程式碼

由此便將 Observable#observeOn(Scheduler) 是如何將下游 Observer 置於指定執行緒執行的流程分析完了。簡而言之 Observable#observeOn(Scheduler) 的實現原理在於將目標 Observer 的 onNext(T)/onError(Throwable)/onComplete() 置於指定執行緒中執行

這裡特別要注意的一點是——【執行緒操作符切換的是其他的流,自身這條流是不會受到影響的。】看過知乎前一段時間的 rx 分享視訊的小夥伴應該有注意到楊凡前輩的 PPT 中有這麼一圖:

這裡寫圖片描述
想要提出兩點——observeOn(Schedulers.io()) 所對應的 Observable 應該是受到了 subscribeOn(AndroidSchedulers.mainThread()) 影響,所以它建立的這條流應該執行於主執行緒;而 subscribeOn(AndroidSchedulers.mainThread()) 所對應的 Observable 則受到了 subscribeOn(Schedulers.computation) 影響,所以它建立的這條流應該執行於 computation 執行緒。

Observable#subscribeOn(Scheduler)

切換 subscribe 執行緒

示例程式碼:
Observable
    .create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(ObservableEmitter<String> emitter) throws Exception {
            emitter.onNext("1");
            Log.e("TAG", "被觀察者所在的執行緒 " + Thread.currentThread().getName());
        }
    })
    .subscribeOn(Schedulers.io())
    .subscribe(new Observer<String>() {
        @Override
        public void onSubscribe(Disposable d) {
            Log.e("TAG", "onSubscribe: " + Thread.currentThread().getName());
        }

        @Override
        public void onNext(String s) {
            Log.e("TAG", "觀察者所線上程為 " + Thread.currentThread().getName());
        }

        @Override
        public void onError(Throwable e) {
        }

        @Override
        public void onComplete() {
        }
    });
複製程式碼

輸出結果:

E/TAG: onSubscribe: main
E/TAG: 觀察者所線上程為 RxCachedThreadScheduler-1
E/TAG: 被觀察者所在的執行緒 RxCachedThreadScheduler-1
複製程式碼

同樣地,戳進 Observable#subscirbeOn(Scheduler) 原始碼,點進 ObservableSubscribeOn 檢視 subscribeActual(Observer) 的具體實現,相信這對於各位讀者來說已經輕車熟路了——

@Override
public void subscribeActual(final Observer<? super T> s) {
    final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);
    s.onSubscribe(parent);
    Disposeable disposable = scheduler.scheduleDirect(new SubscribeTask(parent));
    parent.setDisposable(disposable);
}
複製程式碼

第一行老套路,對下游 Observer 進行了一層封裝;第二行因為它不涉及執行緒切換所以此處也不做擴充套件;第三行就是我們的關鍵了 Scheduler#scheduleDirect(Runnable) 方法可以追溯到 Scheduler#schedule(Runnable, long, TimeUnit),這部分在前面已經闡述過了,就不做擴充套件了。SubscribeTask 是一個 Runnable,它的 run() 核心方法——

@Override
public void run() {
	source.subscribe(parent);
}
複製程式碼

至此謎團解開了,Observable#subscribeOn(Scheduler)Observable#subscribe(Observer) 的執行過程移到了指定執行緒(在上述中也就是 io 執行緒),同時 Observable 和 Observer 中並未做新的執行緒切換處理,所以它們的訂閱、發射等操作就執行在了 io 執行緒。

第一次有效原理

示例程式碼:
Observable
    .create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(ObservableEmitter<String> emitter) throws Exception {
            emitter.onNext("1");
            Log.e("TAG", "被觀察者所在的執行緒 " + Thread.currentThread().getName());
        }
    })
    .subscribeOn(Schedulers.io())
    .subscribeOn(Schedulers.computation())
    .subscribe(new Observer<String>() {
        @Override
        public void onSubscribe(Disposable d) {
            Log.e("TAG", "onSubscribe: " + Thread.currentThread().getName());
        }

        @Override
        public void onNext(String s) {
            Log.e("TAG", "觀察者所線上程為 " + Thread.currentThread().getName());
        }

        @Override
        public void onError(Throwable e) {
        }

        @Override
        public void onComplete() {
        }
    });
複製程式碼

列印結果:

onSubscribe: main
觀察者所線上程為 RxCachedThreadScheduler-1
被觀察者所在的執行緒 RxCachedThreadScheduler-1
複製程式碼

我們知道,只有第一個 Observable#subscribeOn(Scheduler) 操作才有用,而後續的 Observable#subscribeOn(Scheduler) 並不會影響整個流程中 Observerable 。同樣的,來張圖——

示例圖

前面我們分析到,Observable#subscribeOn(Scheduler) 實際上是將 Observable#subscribe(Observer) 的操作放在了指定執行緒,而通過友好 RxJava2.x 原始碼解析(一)基本訂閱流程一文我們知道了 subscribe 的過程是由下往上的。所以首先是第三個 Observable 呼叫 Observable#subscribe(Observer) 啟動訂閱,在其內部會啟用第二個 Observable 的 Observable#subscribe(Observer) 方法,但是此時該方法外部被套入了一個 Schedulers.computation() 執行緒,於是這個訂閱的過程就被執行在了該執行緒中。同樣的,我們不妨用虛擬碼演示一下——

public class Observable {
    // 第「二」個 Observable
    Observable source;
    Observer observer;

    public Observable(Observable source, Observer observer) {
        this.source = source;
        this.observer = observer;
    }

    public void subscribe(Observer Observer) {
        new Thread("computation") {
            @Override
            public void run() {
                // 第「二」個 Observable 訂閱
                source.subscribe(observer);
            }
        }
    }
}
複製程式碼

再往上走,第二個 Observable 訂閱內部會啟用第一個 Observable 的 Observable#subscribe(Observer) 方法,同樣的,該方法被套在了 Schedulers.io() 執行緒中,如下——

public class Observable {
    // 第「一」個 Observable
    Observable source;
    Observer observer;

    public Observable(Observable source, Observer observer) {
        this.source = source;
        this.observer = observer;
    }

    public void subscribe(Observer Observer) {
        new Thread("io") {
            @Override
            public void run() {
                // 第「一」個 Observable 訂閱
                source.subscribe(observer);
            }
        }
    }
}
複製程式碼

此時到達第一個 Observable 了之後就要開始發射事件了,此時的執行執行緒很明顯是 io 執行緒。還可以換成 Thread 虛擬碼來表示 ——

new Thread("computation") {
    @Override
    public void run() {
        // 第二個 Observable.subscribe(Observer) 的實質
        // 就是切換執行緒,效果類似如下
        new Thread("io") {
            @Override
            public void run() {
                // 第一個 Observable.subscribe(Observer) 的實質
                // 就是發射事件
                System.out.println("onNext(T)/onError(Throwable)/onComplete() 的執行執行緒是: " + Thread
                                   .currentThread().getName());
            }
        } .start();
    }
} .start();
複製程式碼

輸出結果:

onNext(T)/onError(Throwable)/onComplete() 的執行執行緒是: io
複製程式碼

Observable#observeOn(Scheduler) 和 Observable#subscribeOn(Scheduler)

如果針對前面的內容你已經懂了,那麼後續的內容可以直接跳過啦,本文就結束了~如果你還沒懂,筆者再彙總一次。

經過友好 RxJava2.x 原始碼解析(一)基本訂閱流程一文我們知道,Observable#subscribe(Observer) 的順序是由下往上的,本遊會將 Observer 進行「封裝」,然後「啟用上游Observable 訂閱這個 Observer」

我們不妨抽象一個 Observer,如下:

public class Observer<T> {
    public void onNext(T t){}
    public void onCompelete(){}
    public void onError(Throwable t){}
}
複製程式碼

對於 Observable#observeOn(Schedulers.computation()) 操作來說,它對 Observer 進行了怎樣的封裝呢?

public class NewObserver<T> {
    // 下游 Observer
    Observer downStreamObserver;
    public NewObserver(Observer observer) {
        downStreamObserver = observer;
    }

    public void onNext(T t) {
        new Thread("computation") {
            downStreamObserver.onNext(t);
        }
    }

    public void onError(Throwable e) {
        new Thread("computation") {
            downStreamObserver.onError(e);
        }
    }

    public void onComplete() {
        new Thread("computation") {
            downStreamObserver.onComplete();
        }
    }
}
複製程式碼

Observable#observeOn(Scheduler) 內部,其對下游的 Observer 進行了類似如上的封裝,這就導致了其「下游」 Observer 在指定執行緒內執行。所以 Observable#observeOn(Scheduler) 是可以多次呼叫並有效的。

而對於 Observable#subscribe(Scheduler) 來說,它並未對下游 Observer 進行封裝,但是對於「啟用上游 Observable 訂閱這個 Observer」這個操作它做了一點小小的手腳,也就是切換執行緒,我們抽象如下——

public class ComputationObservable {
    public void subscribe(observer) {
        new Thread("computation") {
            // upstreamObservable 是上游 Observable,我們不妨假設是下文中所提到的 IOObservable
            upstreamObservable.subscribe(observer);
        }
    }
}
複製程式碼

而當它在往上遇到了一個新的 Observable#subscribe(Scheduler) 操作的時候——

public class IOObservable {
    public void subscribe(observer) {
        new Thread("io") {
            // upstreamObservable 是上游 Observable,我們不妨下文中所提到的 TopObservable
            upstreamObservable.subscribe(observer);
        }
    }
}
複製程式碼

我們不妨假設此時已經到達了最頂端開始發射事件了——

public class TopObservable {
    public void subscribe(observer) {
        observer.onNext(t);
    }
}
複製程式碼

此時的 Observer#onNext(t) 的執行環境當然就是由最後一個 subscribeOn(Scheduler) 操作符(此處的最後一個是指訂閱流程中的最後一個,它與實際寫程式碼的順序相反,也就是我們程式碼中的第一個 subscribeOn(Scheduler) 操作符)所決定的了,在上述虛擬碼中也就是 io 執行緒,虛擬碼對應的原始碼如下——

Observable
    .create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(ObservableEmitter<String> emitter) throws Exception {
            emitter.onNext("1");
        }
    })
    .subscribeOn(Schedulers.io())
    .subscribeOn(Schedulers.computation())
    .subscribe(new Observer<String>() {
        @Override
        public void onSubscribe(Disposable d) {
        }

        @Override
        public void onNext(String s) {
        }

        @Override
        public void onError(Throwable e) {
        }

        @Override
        public void onComplete() {
        }
    });複製程式碼

相關文章