RxJava入門與提高-線程控制Scheduler篇(4)

前言

Scheduler 的 API

在RxJava 中,Scheduler ——調(diào)度器,相當于線程控制器,RxJava 通過它來指定每一段代碼應(yīng)該運行在什么樣的線程。
RxJava 已經(jīng)內(nèi)置了幾個 Scheduler ,它們已經(jīng)適合大多數(shù)的使用場景:

  • Schedulers.immediate(): 直接在當前線程運行,相當于不指定線程。這是默認的 Scheduler。
  • Schedulers.newThread(): 總是啟用新線程,并在新線程執(zhí)行操作。
  • Schedulers.io(): I/O 操作(讀寫文件、讀寫數(shù)據(jù)庫、網(wǎng)絡(luò)信息交互等)所使用的 Scheduler。行為模式和 newThread() 差不多,區(qū)別在于 io() 的內(nèi)部實現(xiàn)是是用一個無數(shù)量上限的線程池,可以重用空閑的線程,因此多數(shù)情況下 io() 比 newThread() 更有效率。不要把計算工作放在 io() 中,可以避免創(chuàng)建不必要的線程。
  • Schedulers.computation(): 計算所使用的 Scheduler。這個計算指的是 CPU 密集型計算,即不會被 I/O 等操作限制性能的操作,例如圖形的計算。這個 Scheduler 使用的固定的線程池,大小為 CPU 核數(shù)。不要把 I/O 操作放在 computation() 中,否則 I/O 操作的等待時間會浪費 CPU。
  • AndroidSchedulers.mainThread(), Android 還有一個專用的 ,它指定的操作將在 Android 主線程運行。
    有了這幾個 Scheduler ,就可以使用subscribeOn() 和 observeOn() 兩個方法來對線程進行控制了。
    (1)subscribeOn(): 指定 subscribe() 所發(fā)生的線程,即 Observable.OnSubscribe 被激活時所處的線程。或者叫做事件產(chǎn)生的線程。
    (2)observeOn(): 指定 Subscriber 所運行在的線程。或者叫做事件消費的線程。

線程操作的知識

先看兩個栗子:

栗子1
Observable.create(new Observable.OnSubscribe<String>() {
                   @Override
                   public void call(Subscriber<? super String> subscriber) {
                       Logger.v( "rx_call" , Thread.currentThread().getName()  );
 
                       subscriber.onNext( "dd");
                       subscriber.onCompleted();
                   }
               })
 
               .subscribeOn(Schedulers.io())
               .observeOn(AndroidSchedulers.mainThread())
 
               .map(new Func1<String, String >() {
                   @Override
                   public String call(String s) {
                       Logger.v( "rx_map" , Thread.currentThread().getName()  );
                       return s + "88";
                   }
               })
               .subscribe(new Action1<String>() {
                   @Override
                   public void call(String s) {
                       Logger.v( "rx_subscribe" , Thread.currentThread().getName()  );
                   }
               }) ;
結(jié)果
/rx_call: RxCachedThreadScheduler-1    --io線程
/rx_map: main                                     --主線程
/rx_subscribe: main                              --主線程

 栗子2
Observable.create(new Observable.OnSubscribe<String>() {
                   @Override
                   public void call(Subscriber<? super String> subscriber) {
                       Logger.v( "rx_call" , Thread.currentThread().getName()  );
 
                       subscriber.onNext( "dd");
                       subscriber.onCompleted();
                   }
               })
               .map(new Func1<String, String >() {
                   @Override
                   public String call(String s) {
                       Logger.v( "rx_map" , Thread.currentThread().getName()  );
                       return s + "88";
                   }
               })
 
               .subscribeOn(Schedulers.io())
               .observeOn(AndroidSchedulers.mainThread())
 
               .subscribe(new Action1<String>() {
                   @Override
                   public void call(String s) {
                       Logger.v( "rx_subscribe" , Thread.currentThread().getName()  );
                   }
               }) ; 
結(jié)果
/rx_call: RxCachedThreadScheduler-1     --io線程
/rx_map: RxCachedThreadScheduler-1   --io線程
/rx_subscribe: main                 --主線程

分析上面兩個栗子,結(jié)論

  • create() , just() , from() 等 --- 事件產(chǎn)生
  • map() , flapMap() , scan() , filter() 等 -- 事件加工
  • subscribe() -- 事件消費

事件產(chǎn)生:默認運行在當前線程,可以由 subscribeOn() 自定義線程
事件加工:默認跟事件產(chǎn)生的線程保持一致, 可以由 observeOn() 自定義線程
事件消費:默認運行在當前線程,可以有observeOn() 自定義

結(jié)論

  • subscribeOn 作用于該操作符之前的 Observable 的創(chuàng)建操符作以及 doOnSubscribe 操作符,換句話說就是 doOnSubscribe 以及 Observable 的創(chuàng)建操作符總是被其之后最近的 subscribeOn 控制。多次調(diào)用,創(chuàng)建操作符除了最近的外,其余無效。

  • observeOn() 設(shè)定事件加工和消費的線程,可以調(diào)用多次,每次調(diào)用只對后邊的操作產(chǎn)生影響。或者這樣說,observeOn作用于該操作符之后操作符直到出現(xiàn)新的observeOn操作符。

subscribeOn

image.png

查看log,這里,模塊3執(zhí)行,它后邊沒有設(shè)置線程,是main。
模塊2執(zhí)行,它后邊設(shè)置了IO線程,所以領(lǐng)打印“doOnSubscribe1:RxIoScheduler-2”
模塊1執(zhí)行,也就是創(chuàng)建create方法執(zhí)行,它后邊有兩個subscribeOn(),只有離他最近 的才會起作用。

image.png

observeOn

結(jié)論:observeOn作用于該操作符之后操作符直到出現(xiàn)新的observeOn操作符

image.png

image.png

圖片解釋:
圖中有兩個observeOn()方法,豎向的箭頭方向可以認為是Rxjava內(nèi)部變化方向,橫向的箭頭可以認為是程序執(zhí)行方向,顏色可以認為是不同的線程。
由圖可以看出,每次豎直方向經(jīng)過observeOn(),程序的執(zhí)行顏色都會變化為observeOn()設(shè)定的顏色,直到再次執(zhí)行observeOn()方法。
也就是 observeOn作用于該操作符之后操作符直到出現(xiàn)新的observeOn操作符

本文對應(yīng)源碼不做分析,只是講述結(jié)論性的知識。


歡迎繼續(xù)收看:RxJava入門與提高-網(wǎng)絡(luò)Retrofit 篇(5)
作者:ZhangYushui
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 作者寄語 很久之前就想寫一個專題,專寫Android開發(fā)框架,專題的名字叫 XXX 從入門到放棄 ,沉淀了這么久,...
    戴定康閱讀 7,648評論 13 85
  • 我從去年開始使用 RxJava ,到現(xiàn)在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的...
    Jason_andy閱讀 5,561評論 7 62
  • 最近項目里面有用到Rxjava框架,感覺很強大的巨作,所以在網(wǎng)上搜了很多相關(guān)文章,發(fā)現(xiàn)一片文章很不錯,今天把這篇文...
    Scus閱讀 6,894評論 2 50
  • 今天在線考試中需要監(jiān)聽手機端的返回鍵,當點擊手機返回鍵時,跳出彈框,是否XX,點擊是,返回。點擊否,不進行任何操作...
    lusiKong閱讀 2,889評論 0 1
  • 《用戶體驗的要素》看完有一段時間了,試著用用戶體驗要素里的五層分析下ZAKER新聞客戶端這款產(chǎn)品: 戰(zhàn)略層:為用戶...
    2c5994723157閱讀 962評論 0 1