如需下載源碼,請訪問
https://github.com/fengchuanfang/Rxjava2Tutorial
文章原創(chuàng),轉(zhuǎn)載請注明出處:
Rxjava2入門教程四:Scheduler線程調(diào)度器
Scheduler(線程調(diào)度器)賦予RxJava簡潔明了的異步操作,可以說是RxJava中最值得稱道的地方。
在之前的代碼中,Observable發(fā)射數(shù)據(jù)流,Observer接收響應(yīng)數(shù)據(jù)流,以及Operators加工數(shù)據(jù)流均是在同一個線程中,實(shí)現(xiàn)出來的是一個同步的函數(shù)響應(yīng)式。但是函數(shù)響應(yīng)式的實(shí)際應(yīng)用卻不是這樣的,大部分都是后臺處理,前臺響應(yīng)的一個過程。Observable生成發(fā)射數(shù)據(jù)流,以及Operators加工數(shù)據(jù)流都是在后臺線程中進(jìn)行,而Observer在前臺線程中接受并相應(yīng)數(shù)據(jù)。
Scheduler(線程調(diào)度器)可以讓RxJava的線程切換變得簡單明了,即使程序邏輯變得十分復(fù)雜,他依然能夠保持簡單明了。
subscribeOn
Observable<T> subscribeOn(Scheduler scheduler)
subscribeOn通過接收一個Scheduler參數(shù),來指定對數(shù)據(jù)的處理運(yùn)行在特定的線程調(diào)度器Scheduler上。
若多次設(shè)定,則只有一次起作用。
observeOn
Observable<T> observeOn(Scheduler scheduler)
observeOn同樣接收一個Scheduler參數(shù),來指定下游操作運(yùn)行在特定的線程調(diào)度器Scheduler上。
若多次設(shè)定,每次均起作用。
Scheduler種類
Schedulers.io(?):
用于IO密集型的操作,例如讀寫SD卡文件,查詢數(shù)據(jù)庫,訪問網(wǎng)絡(luò)等,具有線程緩存機(jī)制,在此調(diào)度器接收到任務(wù)后,先檢查線程緩存池中,是否有空閑的線程,如果有,則復(fù)用,如果沒有則創(chuàng)建新的線程,并加入到線程池中,如果每次都沒有空閑線程使用,可以無上限的創(chuàng)建新線程。
Schedulers.newThread(?):
在每執(zhí)行一個任務(wù)時創(chuàng)建一個新的線程,不具有線程緩存機(jī)制,因?yàn)閯?chuàng)建一個新的線程比復(fù)用一個線程更耗時耗力,雖然使用Schedulers.io(?)的地方,都可以使用Schedulers.newThread(?),但是,Schedulers.newThread(?)的效率沒有Schedulers.io(?)高。
Schedulers.computation():
用于CPU 密集型計算任務(wù),即不會被 I/O 等操作限制性能的耗時操作,例如xml,json文件的解析,Bitmap圖片的壓縮取樣等,具有固定的線程池,大小為CPU的核數(shù)。不可以用于I/O操作,因?yàn)镮/O操作的等待時間會浪費(fèi)CPU。
Schedulers.trampoline():
在當(dāng)前線程立即執(zhí)行任務(wù),如果當(dāng)前線程有任務(wù)在執(zhí)行,則會將其暫停,等插入進(jìn)來的任務(wù)執(zhí)行完之后,再將未完成的任務(wù)接著執(zhí)行。
Schedulers.single():
擁有一個線程單例,所有的任務(wù)都在這一個線程中執(zhí)行,當(dāng)此線程中有任務(wù)執(zhí)行時,其他任務(wù)將會按照先進(jìn)先出的順序依次執(zhí)行。
Scheduler.from(@NonNull Executor executor):
指定一個線程調(diào)度器,由此調(diào)度器來控制任務(wù)的執(zhí)行策略。
AndroidSchedulers.mainThread():
在Android UI線程中執(zhí)行任務(wù),為Android開發(fā)定制。
注:
在RxJava2中,廢棄了RxJava1中的Schedulers.immediate(?)
在RxJava1中,Schedulers.immediate(?)的作用為在當(dāng)前線程立即執(zhí)行任務(wù),功能等同于RxJava2中的Schedulers.trampoline(?)。
而Schedulers.trampoline(?)在RxJava1中的作用是當(dāng)其它排隊的任務(wù)完成后,在當(dāng)前線程排隊開始執(zhí)行接到的任務(wù),有點(diǎn)像RxJava2中的Schedulers.single(),但也不完全相同,因?yàn)镾chedulers.single()不是在當(dāng)前線程而是在一個線程單例中排隊執(zhí)行任務(wù)。
示例一:使用一次subscribeOn和一次observeOn
運(yùn)行代碼后,控制臺打印如下:
System.out: 發(fā)射線程:RxCachedThreadScheduler-1---->發(fā)射:0
System.out: 發(fā)射線程:RxCachedThreadScheduler-1---->發(fā)射:1
System.out: 接收線程:main---->接收:0
System.out: 發(fā)射線程:RxCachedThreadScheduler-1---->發(fā)射:2
System.out: 接收線程:main---->接收:1
System.out: 發(fā)射線程:RxCachedThreadScheduler-1---->發(fā)射:3
System.out: 接收線程:main---->接收:2
System.out: 發(fā)射線程:RxCachedThreadScheduler-1---->發(fā)射:4
System.out: 接收線程:main---->接收:3
System.out: 接收線程:main---->接收:4
通過subscribeOn(Schedulers.io())指定Observable在Schedulers.io(?)調(diào)度器的線程中,每隔1秒發(fā)射一次數(shù)據(jù),通過observeOn(AndroidSchedulers.mainThread())指定Observer在Android UI線程中接收數(shù)據(jù)。
示例二:使用兩次subscribeOn和一次observeOn
通過subscribeOn(Schedulers.io())指定Observable在Schedulers.io(?)調(diào)度器的線程中,每隔1秒發(fā)射一次數(shù)據(jù),通過subscribeOn(Schedulers.newThread())指定map操作符在Schedulers.newThread()的調(diào)度器線程中處理數(shù)據(jù),通過observeOn(AndroidSchedulers.mainThread())指定Observer在Android UI線程中接收數(shù)據(jù)。
運(yùn)行結(jié)果如下:
System.out: 發(fā)射線程:RxCachedThreadScheduler-1---->發(fā)射:0
System.out: 處理線程:RxCachedThreadScheduler-1---->處理:0
System.out: 發(fā)射線程:RxCachedThreadScheduler-1---->發(fā)射:1
System.out: 接收線程:main---->接收:0
System.out: 處理線程:RxCachedThreadScheduler-1---->處理:1
System.out: 接收線程:main---->接收:1
我們發(fā)現(xiàn)發(fā)射和處理數(shù)據(jù)均是在RxCachedThreadScheduler線程中,第二次通過subscribeOn指定的線程不起作用。
示例三:使用一次subscribeOn和兩次observeOn
通過subscribeOn(Schedulers.io())指定Observable在Schedulers.io(?)調(diào)度器的線程中,每隔1秒發(fā)射一次數(shù)據(jù),通過observeOn(Schedulers.newThread())指定map操作符在Schedulers.newThread()的調(diào)度器線程中處理數(shù)據(jù),通過observeOn(AndroidSchedulers.mainThread())指定Observer在Android UI線程中接收數(shù)據(jù)。
運(yùn)行結(jié)果如下:
System.out: 發(fā)射線程:RxCachedThreadScheduler-1---->發(fā)射:0
System.out: 發(fā)射線程:RxCachedThreadScheduler-1---->發(fā)射:1
System.out: 處理線程:RxNewThreadScheduler-1---->處理:0
System.out: 接收線程:main---->接收:0
System.out: 處理線程:RxNewThreadScheduler-1---->處理:1
System.out: 接收線程:main---->接收:1
與我們的預(yù)期結(jié)果一致
通過示例一二三,我們可以總結(jié)subscribeOn和observeOn的用法如下:
subscribeOn來指定對數(shù)據(jù)的處理運(yùn)行在特定的線程調(diào)度器Scheduler上,直到遇到observeOn改變線程調(diào)度器若多次設(shè)定,則只有一次起作用。observeOn指定下游操作運(yùn)行在特定的線程調(diào)度器Scheduler上。若多次設(shè)定,每次均起作用。
示例四:Schedulers.trampoline()
通過示例一二三我們可以發(fā)現(xiàn),Observer處理數(shù)據(jù)相比于Observable發(fā)射的數(shù)據(jù)存在滯后的現(xiàn)象,Observable發(fā)射了兩個數(shù)據(jù),Observer才處理了一個,并不是Observable沒發(fā)射一個,Observer就處理一個。
運(yùn)行:
通過Schedulers.trampoline()/設(shè)置觀察者在當(dāng)前線程中處理數(shù)據(jù),并且故意延遲兩秒后在處理
控制臺打印如下:
System.out: 發(fā)射線程:RxCachedThreadScheduler-1---->發(fā)射:0
System.out: 接收線程:RxCachedThreadScheduler-1---->接收:0
System.out: 發(fā)射線程:RxCachedThreadScheduler-1---->發(fā)射:1
System.out: 接收線程:RxCachedThreadScheduler-1---->接收:1
System.out: 發(fā)射線程:RxCachedThreadScheduler-1---->發(fā)射:2
System.out: 接收線程:RxCachedThreadScheduler-1---->接收:2
System.out: 發(fā)射線程:RxCachedThreadScheduler-1---->發(fā)射:3
System.out: 接收線程:RxCachedThreadScheduler-1---->接收:3
System.out: 發(fā)射線程:RxCachedThreadScheduler-1---->發(fā)射:4
System.out: 接收線程:RxCachedThreadScheduler-1---->接收:4
我們可以發(fā)現(xiàn)雖然Observer在接收到數(shù)據(jù)后,延遲了兩秒才處理,但是Observable依然在Observer將數(shù)據(jù)處理完之后才開始發(fā)射下一條。Schedulers.trampoline()的作用在當(dāng)前線程立即執(zhí)行任務(wù),如果當(dāng)前線程有任務(wù)在執(zhí)行,則會將其暫停,等插入進(jìn)來的任務(wù)執(zhí)行完之后,再將未完成的任務(wù)接著執(zhí)行。
示例五:Schedulers.single()
運(yùn)行結(jié)果如下:
System.out: 發(fā)射線程:RxSingleScheduler-1---->發(fā)射:0
System.out: 發(fā)射線程:RxSingleScheduler-1---->發(fā)射:1
System.out: 發(fā)射線程:RxSingleScheduler-1---->發(fā)射:2
System.out: 處理線程:RxSingleScheduler-1---->處理:0
System.out: 處理線程:RxSingleScheduler-1---->處理:1
System.out: 處理線程:RxSingleScheduler-1---->處理:2
System.out: 接收線程:RxSingleScheduler-1---->接收:0
System.out: 接收線程:RxSingleScheduler-1---->接收:1
System.out: 接收線程:RxSingleScheduler-1---->接收:2
通過Schedulers.single()將數(shù)據(jù)的發(fā)射,處理,接收在Schedulers.single()的線程單例中排隊執(zhí)行,當(dāng)此線程中有任務(wù)執(zhí)行時,其他任務(wù)將會按照先進(jìn)先出的順序依次執(zhí)行。
上一篇:Rxjava2入門教程三:Operators操作符
下一篇:Rxjava2入門教程五:Flowable背壓支持