Rxjava2入門教程四:Scheduler線程調度器

Scheduler(線程調度器)賦予RxJava簡潔明瞭的異步操作,可以說是RxJava中最值得稱道的地方。
在之前的代碼中,Observable發射數據流,Observer接收響應數據流,以及Operators加工數據流均是在同一個線程中,實現出來的是一個同步的函數響應式。但是函數響應式的實際應用卻不是這樣的,大部分都是後臺處理,前臺響應的一個過程。Observable生成發射數據流,以及Operators加工數據流都是在後臺線程中進行,而Observer在前臺線程中接受並相應數據。
Scheduler(線程調度器)可以讓RxJava的線程切換變得簡單明瞭,即使程序邏輯變得十分複雜,他依然能夠保持簡單明瞭。

subscribeOn

Observable<T> subscribeOn(Scheduler scheduler) 

subscribeOn通過接收一個Scheduler參數,來指定對數據的處理運行在特定的線程調度器Scheduler上。
若多次設定,則只有一次起作用。

observeOn

Observable<T> observeOn(Scheduler scheduler)

observeOn同樣接收一個Scheduler參數,來指定下游操作運行在特定的線程調度器Scheduler上。
若多次設定,每次均起作用。

Scheduler種類

Schedulers.io( ):

用於IO密集型的操作,例如讀寫SD卡文件,查詢數據庫,訪問網絡等,具有線程緩存機制,在此調度器接收到任務後,先檢查線程緩存池中,是否有空閒的線程,如果有,則複用,如果沒有則創建新的線程,並加入到線程池中,如果每次都沒有空閒線程使用,可以無上限的創建新線程。

Schedulers.newThread( ):

在每執行一個任務時創建一個新的線程,不具有線程緩存機制,因爲創建一個新的線程比複用一個線程更耗時耗力,雖然使用Schedulers.io( )的地方,都可以使用Schedulers.newThread( ),但是,Schedulers.newThread( )的效率沒有Schedulers.io( )高。

Schedulers.computation():

用於CPU 密集型計算任務,即不會被 I/O 等操作限制性能的耗時操作,例如xml,json文件的解析,Bitmap圖片的壓縮取樣等,具有固定的線程池,大小爲CPU的核數。不可以用於I/O操作,因爲I/O操作的等待時間會浪費CPU。

Schedulers.trampoline():

在當前線程立即執行任務,如果當前線程有任務在執行,則會將其暫停,等插入進來的任務執行完之後,再將未完成的任務接着執行。

Schedulers.single():

擁有一個線程單例,所有的任務都在這一個線程中執行,當此線程中有任務執行時,其他任務將會按照先進先出的順序依次執行。

Scheduler.from(@NonNull Executor executor):

指定一個線程調度器,由此調度器來控制任務的執行策略。

AndroidSchedulers.mainThread():

在Android UI線程中執行任務,爲Android開發定製。

注:

在RxJava2中,廢棄了RxJava1中的Schedulers.immediate( )
在RxJava1中,Schedulers.immediate( )的作用爲在當前線程立即執行任務,功能等同於RxJava2中的Schedulers.trampoline( )。
而Schedulers.trampoline( )在RxJava1中的作用是當其它排隊的任務完成後,在當前線程排隊開始執行接到的任務,有點像RxJava2中的Schedulers.single(),但也不完全相同,因爲Schedulers.single()不是在當前線程而是在一個線程單例中排隊執行任務。

示例一:使用一次subscribeOn和一次observeOn

運行代碼後,控制檯打印如下:

System.out: 發射線程:RxCachedThreadScheduler-1---->發射:0
System.out: 發射線程:RxCachedThreadScheduler-1---->發射:1
System.out: 接收線程:main---->接收:0
System.out: 發射線程:RxCachedThreadScheduler-1---->發射:2
System.out: 接收線程:main---->接收:1
System.out: 發射線程:RxCachedThreadScheduler-1---->發射:3
System.out: 接收線程:main---->接收:2
System.out: 發射線程:RxCachedThreadScheduler-1---->發射:4
System.out: 接收線程:main---->接收:3
System.out: 接收線程:main---->接收:4

通過subscribeOn(Schedulers.io())指定Observable在Schedulers.io( )調度器的線程中,每隔1秒發射一次數據,通過observeOn(AndroidSchedulers.mainThread())指定Observer在Android UI線程中接收數據。

示例二:使用兩次subscribeOn和一次observeOn

通過subscribeOn(Schedulers.io())指定Observable在Schedulers.io( )調度器的線程中,每隔1秒發射一次數據,通過subscribeOn(Schedulers.newThread())指定map操作符在Schedulers.newThread()的調度器線程中處理數據,通過observeOn(AndroidSchedulers.mainThread())指定Observer在Android UI線程中接收數據。
運行結果如下:

System.out: 發射線程:RxCachedThreadScheduler-1---->發射:0
System.out: 處理線程:RxCachedThreadScheduler-1---->處理:0
System.out: 發射線程:RxCachedThreadScheduler-1---->發射:1
System.out: 接收線程:main---->接收:0
System.out: 處理線程:RxCachedThreadScheduler-1---->處理:1
System.out: 接收線程:main---->接收:1

我們發現發射和處理數據均是在RxCachedThreadScheduler線程中,第二次通過subscribeOn指定的線程不起作用。

示例三:使用一次subscribeOn和兩次observeOn

通過subscribeOn(Schedulers.io())指定Observable在Schedulers.io( )調度器的線程中,每隔1秒發射一次數據,通過observeOn(Schedulers.newThread())指定map操作符在Schedulers.newThread()的調度器線程中處理數據,通過observeOn(AndroidSchedulers.mainThread())指定Observer在Android UI線程中接收數據。
運行結果如下:

System.out: 發射線程:RxCachedThreadScheduler-1---->發射:0
System.out: 發射線程:RxCachedThreadScheduler-1---->發射:1
System.out: 處理線程:RxNewThreadScheduler-1---->處理:0
System.out: 接收線程:main---->接收:0
System.out: 處理線程:RxNewThreadScheduler-1---->處理:1
System.out: 接收線程:main---->接收:1

與我們的預期結果一致

通過示例一二三,我們可以總結subscribeOn和observeOn的用法如下:

subscribeOn來指定對數據的處理運行在特定的線程調度器Scheduler上,直到遇到observeOn改變線程調度器若多次設定,則只有一次起作用。observeOn指定下游操作運行在特定的線程調度器Scheduler上。若多次設定,每次均起作用。

示例四:Schedulers.trampoline()

通過示例一二三我們可以發現,Observer處理數據相比於Observable發射的數據存在滯後的現象,Observable發射了兩個數據,Observer才處理了一個,並不是Observable沒發射一個,Observer就處理一個。
運行:

通過Schedulers.trampoline()/設置觀察者在當前線程中處理數據,並且故意延遲兩秒後在處理
控制檯打印如下:

System.out: 發射線程:RxCachedThreadScheduler-1---->發射:0
System.out: 接收線程:RxCachedThreadScheduler-1---->接收:0
System.out: 發射線程:RxCachedThreadScheduler-1---->發射:1
System.out: 接收線程:RxCachedThreadScheduler-1---->接收:1
System.out: 發射線程:RxCachedThreadScheduler-1---->發射:2
System.out: 接收線程:RxCachedThreadScheduler-1---->接收:2
System.out: 發射線程:RxCachedThreadScheduler-1---->發射:3
System.out: 接收線程:RxCachedThreadScheduler-1---->接收:3
System.out: 發射線程:RxCachedThreadScheduler-1---->發射:4
System.out: 接收線程:RxCachedThreadScheduler-1---->接收:4

我們可以發現雖然Observer在接收到數據後,延遲了兩秒才處理,但是Observable依然在Observer將數據處理完之後纔開始發射下一條。Schedulers.trampoline()的作用在當前線程立即執行任務,如果當前線程有任務在執行,則會將其暫停,等插入進來的任務執行完之後,再將未完成的任務接着執行。

示例五:Schedulers.single()

運行結果如下:

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

System.out: 接收線程:RxSingleScheduler-1---->接收:0
System.out: 接收線程:RxSingleScheduler-1---->接收:1
System.out: 接收線程:RxSingleScheduler-1---->接收:2

通過Schedulers.single()將數據的發射,處理,接收在Schedulers.single()的線程單例中排隊執行,當此線程中有任務執行時,其他任務將會按照先進先出的順序依次執行。



 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章