schedulers詳解

schedulers是RxJava2中非常重要的概念,也是其最為核心的部分之一。schedulers能夠使RxJava2的執行更加高效,可控,能夠有效地防止RxJava2中常見的一些問題,如線程阻塞、卡頓等。本文將從多個方面對schedulers進行詳細的闡述。

一、schedulers介紹

schedulers是RxJava2中用來控制Observable數據源的線程的調度程序,能夠有效地控制Observable的運行、訂閱和發射。RxJava2中提供了許多的schedulers,如Schedulers.io(),Schedulers.newThread(),Schedulers.computation()和AndroidSchedulers.mainThread()等。

為了便於理解schedulers的作用,我們來看一下下面這個例子:

Observable.create(new ObservableOnSubscribe() {
    @Override
    public void subscribe(ObservableEmitter emitter) throws Exception {
        Log.d(TAG, "Observable thread is : " + Thread.currentThread().getName());
        emitter.onNext(1);
    }
}).subscribe(new Consumer() {
    @Override
    public void accept(Integer integer) throws Exception {
        Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
    }
});

在這個例子中,我們在Observable中發射了數字1並在Observer中接收這個數字。我們打印出了Observable和Observer所在的線程名。如果我們不使用schedulers,我們會發現Observable和Observer都在同一個線程中,即主線程中。這樣的話,就可能會出現Observable中執行耗時操作導致主線程卡頓或者ANR的問題。

那麼,我們可以使用schedulers來改變Observable和Observer所在的線程。例如,我們可以使用Schedulers.newThread()將Observable切換到一個新的線程中:

Observable.create(new ObservableOnSubscribe() {
    @Override
    public void subscribe(ObservableEmitter emitter) throws Exception {
        Log.d(TAG, "Observable thread is : " + Thread.currentThread().getName());
        emitter.onNext(1);
    }
}).subscribeOn(Schedulers.newThread()).subscribe(new Consumer() {
    @Override
    public void accept(Integer integer) throws Exception {
        Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
    }
});

這樣,Observable就會切換到一個新的線程中執行,而Observer仍然在主線程中執行。

二、schedulers的類型

RxJava2中提供了多種schedulers類型,每種類型都有不同的用途:

1. Schedulers.io()

Schedulers.io()是一個異步任務線程池,用於執行I/O操作或延遲任務。它比Schedulers.newThread()更有效,因為在同一時間可以有多個I/O操作運行在Schedulers.io()線程池中,而Schedulers.newThread()始終只能運行一個線程。

Observable.create(new ObservableOnSubscribe() {
    @Override
    public void subscribe(ObservableEmitter emitter) throws Exception {
        Log.d(TAG, "Observable thread is : " + Thread.currentThread().getName());
        emitter.onNext(1);
    }
}).subscribeOn(Schedulers.io()).subscribe(new Consumer() {
    @Override
    public void accept(Integer integer) throws Exception {
        Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
    }
});

2. Schedulers.newThread()

Schedulers.newThread()會創建一個新的線程執行任務。如果你沒有為任務創建專門的線程池,它就會為你創建線程。

Observable.create(new ObservableOnSubscribe() {
    @Override
    public void subscribe(ObservableEmitter emitter) throws Exception {
        Log.d(TAG, "Observable thread is : " + Thread.currentThread().getName());
        emitter.onNext(1);
    }
}).subscribeOn(Schedulers.newThread()).subscribe(new Consumer() {
    @Override
    public void accept(Integer integer) throws Exception {
        Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
    }
});

3. Schedulers.computation()

Schedulers.computation()會創建一個固定大小的線程池,用於執行CPU密集型操作,比如數學運算。它的線程池大小默認為CPU內核數量,但你也可以通過調用Schedulers.computation(int n)來使用不同大小的線程池。

Observable.create(new ObservableOnSubscribe() {
    @Override
    public void subscribe(ObservableEmitter emitter) throws Exception {
        Log.d(TAG, "Observable thread is : " + Thread.currentThread().getName());
        emitter.onNext(1);
    }
}).subscribeOn(Schedulers.computation()).subscribe(new Consumer() {
    @Override
    public void accept(Integer integer) throws Exception {
        Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
    }
});

4. AndroidSchedulers.mainThread()

AndroidSchedulers.mainThread()是在Android中使用的schedulers類型,它會將任務切換到Android主線程中運行。一般用於將結果通知給UI組件。

Observable.just(1, 2, 3, 4)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Consumer() {
            @Override
            public void accept(Integer integer) throws Exception {
                Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
                textView.setText(String.valueOf(integer));
            }
        });

三、鏈式調用和指定線程

在RxJava2中,我們可以使用鏈式調用來指定Observable和Observer的線程:

Observable.just(1, 2, 3, 4)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Consumer() {
            @Override
            public void accept(Integer integer) throws Exception {
                Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
                textView.setText(String.valueOf(integer));
            }
        });

在這個例子中,我們先使用just創建了一個包含數字1-4的Observable,然後使用subscribeOn指定Observable的線程為io線程。接着使用observeOn將Observer的線程切換到Android主線程中。最後,在subscribe中指定接收Observable發射出的整數,並將其設置為textView的內容。

四、指定多個線程

有時候,我們需要在不同的地方指定不同的線程,這時我們可以使用RxJava2中的更高級的方法。例如,我們可以使用flatMap來指定多個不同的線程:

Observable.just(1, 2, 3)
        .flatMap(new Function<Integer, ObservableSource>() {
            @Override
            public ObservableSource apply(Integer integer) throws Exception {
                return Observable.just(String.valueOf(integer))
                        .subscribeOn(Schedulers.newThread())
                        .map(new Function() {
                            @Override
                            public String apply(String s) throws Exception {
                                Log.d(TAG, "map apply thread is : " + Thread.currentThread().getName());
                                return s + " mapped to " + Thread.currentThread().getName();
                            }
                        })
                        .observeOn(AndroidSchedulers.mainThread());
            }
        })
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Consumer() {
            @Override
            public void accept(String s) throws Exception {
                Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
                Log.d(TAG, "accept: " + s);
            }
        });

在這個例子中,我們使用flatMap將Observable中的每個整數轉換為一個新的Observable。在新的Observable中,我們先使用subscribeOn將線程切換到新的線程中,然後使用map進行數據轉換並指定線程,最後使用observeOn將線程切換回主線程中。在subscribe中我們指定接收字符串數據並打印出來。

總結

本文從介紹schedulers,schedulers的類型,鏈式調用和指定線程以及指定多個線程4個方面對schedulers進行了詳細的闡述。如果在RxJava2的開發中沒有使用schedulers,就意味着你失去了很多優化和控制的機會。通過本文,希望大家可以更好地理解和使用schedulers。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/153104.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-11-14 03:03
下一篇 2024-11-14 03:03

相關推薦

  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁盤中。在執行sync之前,所有的文件系統更新將不會立即寫入磁盤,而是先緩存在內存…

    編程 2025-04-25
  • 神經網絡代碼詳解

    神經網絡作為一種人工智能技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網絡的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網絡模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • Linux修改文件名命令詳解

    在Linux系統中,修改文件名是一個很常見的操作。Linux提供了多種方式來修改文件名,這篇文章將介紹Linux修改文件名的詳細操作。 一、mv命令 mv命令是Linux下的常用命…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性傳感器,能夠同時測量加速度和角速度。它由三個傳感器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25
  • C語言貪吃蛇詳解

    一、數據結構和算法 C語言貪吃蛇主要運用了以下數據結構和算法: 1. 鏈表 typedef struct body { int x; int y; struct body *nex…

    編程 2025-04-25
  • Python輸入輸出詳解

    一、文件讀寫 Python中文件的讀寫操作是必不可少的基本技能之一。讀寫文件分別使用open()函數中的’r’和’w’參數,讀取文件…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變量讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25
  • Java BigDecimal 精度詳解

    一、基礎概念 Java BigDecimal 是一個用於高精度計算的類。普通的 double 或 float 類型只能精確表示有限的數字,而對於需要高精度計算的場景,BigDeci…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web服務器。nginx是一個高性能的反向代理web服務器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25

發表回復

登錄後才能評論