RxJava排程器的選擇

知秋z發表於2019-06-24

前提:

在RxJava中有5種不同的排程程式可供選擇:

  1. immediate():建立並返回一個在當前執行緒上立即執行工作的Scheduler。
  2. trampoline():建立並返回一個Scheduler ,該Scheduler 所線上程並不會立即工作,而是要等待我們所設定的等待時間結束後才可以執行(預設為0),當然,這個延時設定是要設定在Runnable實現內部。還有一點就是所有任務要新增到一個佇列中,然後依次執行即可。
  3. newThread():建立並返回一個Scheduler,為每個任務建立一個新的Thread。
  4. computation():建立並返回用於計算工作的Scheduler。它可以用於事件迴圈,處理回撥和其他計算工作。注意不要使用該Scheduler執行IO型別的工作,對此,我們可以使用io() 代替。
  5. io() :建立並返回一個用於IO型別工作的Scheduler。該實現維護了一個Executor執行緒池,該執行緒池可根據需要增長。該Scheduler可用於非同步執行阻塞IO。不要使用該Scheduler執行計算任務。

問題:

前3個Scheduler解釋的非常到位,對computation()io() 有點困惑。

  1. 究竟什麼是“IO-bound work”?它適用於處理streams(java.io)和files(java.nio.files)嗎?適用於資料庫查詢嗎?適用於下載檔案還是訪問REST API?
  2. computation()newThread() 有什麼不同之處?
  3. 為什麼在進行IO任務時呼叫computation() 會很糟糕?
  4. 為什麼在進行計算任務時呼叫io() 會很糟糕?

答案:

很棒的問題,我認為文件可以提供更多細節。

  1. io()由無限制執行緒數量的執行緒池支援,用於執行非計算密集型任務,這些任務不會對CPU造成太大負擔(比如主機板上的南北橋晶片,南橋晶片主要負責軟碟機、硬碟、鍵盤以及附加卡的資料交換)。因此,與檔案系統的互動,與不同主機上的資料庫或服務的互動就是很好的適用場景。
  2. computation()由有限數量的執行緒池支援,其大小等於可用處理器的數量。如果你試圖在可用處理器之外並行安排cpu密集型工作(比如使用newThread()),那麼當執行緒爭奪處理器時,你就會面臨執行緒建立開銷和上下文切換開銷,並且它可能會受到很大的效能影響。
  3. 最好只留下computation()CPU密集型工作,否則你將無法獲得良好的CPU利用率。
  4. io()根據2中所講,在進行計算任務時使用io()是很不好的,如果你io()並行安排了一千個計算任務,那麼這千個任務中的每一個都將擁有自己的執行緒並爭奪CPU產生的上下文切換成本。

本文配套擴充視訊講解:

Rxjava問題集之RxJava排程器的選擇01

Rxjava問題集之RxJava排程器的選擇02

相關文章