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/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

发表回复

登录后才能评论