RxJava线程小结

参考

https://www.jianshu.com/p/73c207844bb4
https://blog.csdn.net/mq2553299/article/details/78725846

implementation "io.reactivex.rxjava2:rxjava:2.1.7"
implementation "io.reactivex.rxjava2:rxandroid:2.0.1"

Rxjava 线程调度的控制

subscribeOn()

Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter e) throws Exception {
                Log.e("zzz", Thread.currentThread().getName() + "\t111");
                e.onNext(1);
            }
        }).subscribeOn(Schedulers.computation())
                .map(new Function() {
                    @Override
                    public Integer apply(Integer integer) throws Exception {
                        Log.e("zzz", Thread.currentThread().getName() + "\t222");
                        return integer;
                    }
                }).subscribeOn(Schedulers.io()).map(new Function() {
            @Override
            public Integer apply(Integer integer) throws Exception {
                Log.e("zzz", Thread.currentThread().getName() + "\t333");
                return integer;
            }
        }).subscribeOn(Schedulers.newThread()).map(new Function() {
            @Override
            public Integer apply(Integer integer) throws Exception {
                Log.e("zzz", Thread.currentThread().getName() + "\t444");
                return integer;
            }
        }).subscribeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer() {
                    @Override
                    public void accept(Integer integer) throws Exception {
                        Log.e("zzz", Thread.currentThread().getName() + "\t555");
                    }
                });

打印结果

E/zzz: RxComputationThreadPool-1    111
E/zzz: RxComputationThreadPool-1    222
E/zzz: RxComputationThreadPool-1    333
E/zzz: RxComputationThreadPool-1    444
E/zzz: RxComputationThreadPool-1    555

subscribeOn() 只对上游有用,当存在多个subscribeOn()方法时,仅第一个(上到下)subscribeOn()有效。

observerOn()

Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter e) throws Exception {
                Log.e("zzz", Thread.currentThread().getName() + "\t111");
                e.onNext(1);
            }
        }).subscribeOn(Schedulers.computation())
                .observeOn(AndroidSchedulers.mainThread())
                .map(new Function() {
                    @Override
                    public Integer apply(Integer integer) throws Exception {
                        Log.e("zzz", Thread.currentThread().getName() + "\t222");
                        return integer;
                    }
                }).observeOn(Schedulers.io()).map(new Function() {
            @Override
            public Integer apply(Integer integer) throws Exception {
                Log.e("zzz", Thread.currentThread().getName() + "\t333");
                return integer;
            }
        }).observeOn(Schedulers.newThread()).map(new Function() {
            @Override
            public Integer apply(Integer integer) throws Exception {
                Log.e("zzz", Thread.currentThread().getName() + "\t444");
                return integer;
            }
        }).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer() {
                    @Override
                    public void accept(Integer integer) throws Exception {
                        Log.e("zzz", Thread.currentThread().getName() + "\t555");
                    }
                });

结果

E/zzz: RxComputationThreadPool-1    111
E/zzz: main 222
E/zzz: RxCachedThreadScheduler-1    333
E/zzz: RxNewThreadScheduler-1   444
E/zzz: main 555 

observerOn()仅对下游生效,并且,如果多次调用,observerOn()的线程调度会持续到下一个observerOn()操作之前。

了解Scheduler

RxJava中的多线程操作主要是由强大的Scheduler集合提供的。在RxJava中,我们无法直接访问或操作线程。如果想要使用线程的话,必须要通过内置的Scheduler来实现。

你可以将Scheduler视为线程池(一个线程的集合),能够执行不同类型的工作。

简而言之,如果你需要在特定的线程中执行任务的话,我们就需要此选择恰当的Scheduler,Scheduler接下来会从它的池中获取一个可用的线程,并基于该线程执行任务。

在RxJava框架中有多种类型的Scheduler,但是这里比较有技巧的一点就是为合适的工作选择恰当的Scheduler。

如果你没有选择恰当的Scheduler的话,那么任务就无法最优地运行,所以接下来,我们尝试理解每一个Scheduler。

Schedulers.io()

这是由无边界线程池作为支撑的一个Scheduler,它适用于非CPU密集的I/O工作,比如访问文件系统、执行网络调用、访问数据库等等。这个Scheduler是没有限制的,它的线程池可以按需一直增长。

Schedulers.computation()

这个Scheduler用于执行CPU密集的工作,比如处理大规模的数据集、图像处理等等。它由一个有界的线程池作为支撑,线程的最大数量就是可用的处理器数量。

因为这个Scheduler只适用于CPU密集的任务,我们希望限制线程的数量,这样的话,它们不会彼此抢占CPU时间或出现线程饿死的现象。

Schedulers.newThread()

这个Scheduler 每次都会创建一个全新的线程来完成一组工作。它不会从任何线程池中受益,线程的创建和销毁都是很昂贵的,所以你需要非常小心,不要衍生出太多的线程,导致服务器系统变慢或出现内存溢出的错误。

理想情况下,你应该很少使用这个Scheduler,它大多用于在一个完全分离的线程中开始一项长时间运行、隔离的一组任务。

Schedulers.single()

这个Scheduler是RxJava 2新引入的,它的背后只有一个线程作为支撑,只能按照有序的方式执行任务。如果你有一组后台任务要在App的不同地方执行,但是同时只能承受一个任务执行的话,那么这个Scheduler就可以派上用场了。

Schedulers.from(Executor executor)

我们可以使用它创建自定义的Scheduler,它是由我们自己的Executor作为支撑的。在有些场景下,我们希望创建自定义的Scheduler为App执行特定的任务,这些任务可能需要自定义的线程逻辑。

假设,我们想要限制App中并行网络请求的数量,那么我们就可以创建一个自定义的Scheduler,使其具有一个固定线程池大小的Executor:Scheduler.from(Executors.newFixedThreadPool(n)),然后将其应用到代码中所有网络相关的Observable上。

AndroidSchedulers.mainThread()

这是一个特殊的Scheduler,它无法在核心RxJava库中使用,要使用它,必须要借助RxAndroid扩展库。这个Scheduler对Android App特别有用,它能够在应用的主线程中执行基于UI的任务。

默认情况下,它会在应用主线程关联的looper中进行任务排队,但是它有一个其他的变种,允许我们以API的形式使用任意的Looper:AndroidSchedulers.from(Looper looper)。

注意:在使用无边界线程池支撑的Scheduler时,比如Schedulers.io(),我们要特别小心,因为它有可能会导致线程池无限增长,使系统中出现大量的线程。

你可能感兴趣的:(RxJava线程小结)