RxJava2探索-线程切换原理之subscribeOn

前言

说起来有点丢人,上周去某公司面试,做足了什么像java内存模型、hashmap原理、设计模式、Android多线程、自定义View等等相关的知识准备,然而面试的时候,前面几个一个没问!!!自定义view考察了onmeasure和Mnuspace那几个mode以及touch事件传递等,我真想给自己一巴掌,居然把那几个mode给忘了,只记得两个还拼不出单词。。。然后就问了RxJava,虽然没有直接问线程切换原理,但是确实考察的就是线程切换的问题,我只能靠猜了,并且还是以RXJAVA2来问的,因为我的简历上写着了解RXJAVA,不是精通,不是精通,不是精通。结果可想而知。

当然,我并不是说面试官有什么不好的地方,只是恨自己学得还不够多不够深,不善于总结和回顾以前的技能,希望自己知耻而后勇吧。俗话说,吃一堑长一智,面试完回来之后,我就把他所问到的问题全部研究了一遍,希望以后不要再出现上一次的窘境了^_^。

tips:以下所有关于源码的部分都是基于RxJava2.1.15版本

一、为什么要写这个东西

你们肯定觉得我是为了写博客装x用的,或者是为了把学到的知识记录下来,以便于以后查阅。我告诉你们,都不是!今天在这里写这篇文章的原因很简单:我看了很多图文并茂的文章讲述RXJAVA线程切换原理,可是呢,最后我竟然是自己翻源码才实实在在的理解了这个原理的。嘿嘿,对,我就是这个意思,他们写得不够好!今天,我就是要让更多的人很快速的就理解RXJAVA线程切换的原理。

装x完毕,开始一本正经吹牛x了,先盗个图。

二、切换线程的那些事儿

2.1 什么叫线程切换

从程序的角度举个列子,作为一只Android开发攻城狮,大家肯定都能猜到我要以什么列子切入啦,没错,thread+handler更新UI,原始点的方式就是new一个Thread来执行网络请求(子线程),然后通过一个在主线程的handler发送消息到主线程更新UI(主线程),数据就从子线程切换到了主线程。Android里还有一个经典的可以切换线程的东西就是AsyncTask了,这里就不做额外展开了。

换个通俗易懂的例子,我有一片玉米地,玉米成熟了,我请了小明来帮我掰玉米,小明掰完玉米后我让他帮我数一下一共有多少个,小明却说,我没读过书,不会数数,只会掰玉米,没办法,我就请了擅长数学的小红帮我数玉米,小红数完玉米后,我想让她帮我把玉米煮熟了拿来卖,可小红又说了,我只会数玉米,不会煮玉米,我又请了会煮玉米的小刚来帮我煮玉米,然后自己卖玉米了。至此,掰玉米的事情是小明负责的(thread1),数玉米的事情是小红做的(thread2),煮玉米的事情是小刚做的(thread3),他们彼此相互独立却又帮我完成了一整套事情并且效率实现了最大化。

2.2 线程切换有什么用

我们再来看个例子,Android系统告诉你,不允许网络耗时任务发生在主线程哦,好嘛,那我就new一个Thread来执行网络请求嘛,等了半天,数据请求回来了,我开开开心心的把请求到的数据拿去渲染UI,结果,Android系统又告诉你,子线程不能更新UI哦。。。WTF???逗我玩呢么?Android系统又说了,别着急,我给你个小拖车,你把你在new Thread里取到的东西放在小拖车里,小拖车会来给我(主线程)的,大家开开心心,何乐而不为。大家不要喷我,我只是把Handler+Thread这种模式说得复杂了一些。。。

作为一只Android开发攻城狮,这个套路大家肯定早就聊熟于心,闭着眼睛都能写出来,但是,可能很多人像我一样,并没有深究其表示的意义。因为Android操作系统有自己的一些特性(多线程)和规则(不允许网络耗时任务发生在主线程、子线程不能更新UI等),我们不得不保持这些特性和遵守这些规则,在这些特性和规则的束缚下,线程切换就必不可少。

“线程切换的意义”,你们可以去google或是baidu一下,我目前是没有搜索到对应的符合标题的结果的,所以,要么是这个问题太简单,简单到大家不需要问,都能理解;要么就是这个问题本身就没有意义,没有必要去寻求一个定义。我本想,多线程由来已久,都没有人去关注和定义线程切换的意义,那么我就来开个先河吧(一本正经脸),可是我琢磨了好些天,我总是会被Android系统本身或RxJava所束缚,无法站在更高的地方去阐述其意义,所以,关于线程切换的意义,还是等待将来有哪位大神可以分享出来吧。

附上我用google搜索“线程切换的意义”结果截图

三、RxJava2的线程切换

如果还没有RxJava2基础的童鞋,请先去了解下RxJava2在来看下面的内容会更好哦

请各位往这边走,我好推你们下去。。。

传送门《这可能是最好的RxJava 2.x 教程》

ps:如果你们不想去看,也没关系,随便整个工程,引入RxJava2依赖,跟着我的步伐,不停地反复的戳进源码,或许会有另一种意想不到的效果

3.1从一段简单的代码说起

接下来,我们先看个RxJava2的subscribeOn方法切换线程的例子

1.不调用subscribeOn方法指定线程

    Observable.create((ObservableOnSubscribe<Integer>) observableEmitter -> {
                System.out.println("ObservableOnSubscribe.subscribe thread : " + Thread.currentThread().getName());
                observableEmitter.onNext(1);
                observableEmitter.onComplete();
            })//顶层Observable
                    .map(integer -> {
                        System.out.println("map  thread : " + Thread.currentThread().getName());
                        return String.valueOf(integer);
                    })//第二个Observable
                    .filter(s -> {
                        System.out.println("filter  thread : " + Thread.currentThread().getName());
                        return Integer.parseInt(s) > 0;
                    })//第三个Observable
                    .subscribe(new Observer<String>() {
                        @Override
                        public void onSubscribe(Disposable disposable) {
                            System.out.println("onSubscribe  thread : " + Thread.currentThread().getName());
                        }

                        @Override
                        public void onNext(String s) {
                            System.out.println("onNext  thread : " + Thread.currentThread().getName());
                        }

                        @Override
                        public void onError(Throwable throwable) {
                            System.out.println("onError  thread : " + Thread.currentThread().getName());
                        }

                        @Override
                        public void onComplete() {
                            System.out.println("onComplete  thread : " + Thread.currentThread().getName());
                        }
                    });

此时的输出结果如下:

onSubscribe  thread : main
ObservableOnSubscribe.subscribe thread : main
map  thread : main
filter  thread : main
onNext  thread : main
onComplete  thread : main

2.调用一次subscribeOn方法指定线程

      Observable.create((ObservableOnSubscribe<Integer>) observableEmitter -> {
            System.out.println("ObservableOnSubscribe.subscribe thread : " + Thread.currentThread().getName());
            observableEmitter.onNext(1);
            observableEmitter.onComplete();
        })//顶层Observable
               .subscribeOn(Schedulers.io())//第一次subscribeOn
                .map(integer -> {
                    System.out.println("map  thread : " + Thread.currentThread().getName());
                    return String.valueOf(integer);
                })//第二个Observable
                .filter(s -> {
                    System.out.println("filter  thread : " + Thread.currentThread().getName());
                    return Integer.parseInt(s) > 0;
                })//第三个Observable
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable disposable) {
                        System.out.println("onSubscribe  thread : " + Thread.currentThread().getName());
                    }

                    @Override
                    public void onNext(String s) {
                        System.out.println("onNext  thread : " + Thread.currentThread().getName());
                    }

                    @Override
                    public void onError(Throwable throwable) {
                        System.out.println("onError  thread : " + Thread.currentThread().getName());
                    }

                    @Override
                    public void onComplete() {
                        System.out.println("onComplete  thread : " + Thread.currentThread().getName());
                    }
                });

此时的输出结果如下:

onSubscribe  thread : main
ObservableOnSubscribe.subscribe thread : RxCachedThreadScheduler-1
map  thread : RxCachedThreadScheduler-1
filter  thread : RxCachedThreadScheduler-1
onNext  thread : RxCachedThreadScheduler-1
onComplete  thread : RxCachedThr
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值