抱着陌生的态度再看Rxjava(二)
来源:互联网 发布:巨人网络街篮客服 编辑:程序博客网 时间:2024/05/21 15:00
如果你已经有了Rxjava1的使用基础,你可以看一下这一篇的大体的提纲,了解就可以链接到三,说不定三都不用看。。
如果没有Rxjava1的基础,就 定心点,小脚并并拢,坐正了往下看。
subscribeOn和observeOn
初见
我们之前在尝试
Observable
或者是Flowable
的subscribe方法时候,有没有在意IDE自动帮我们弹出的方法里有subscribeOn
这个鬼,于是我又好奇的点开Observable的源码,搜了下observeOn
,结果也有。看了下注释,比较抽象。按照我们的chinglish直接从方法上来翻译是在什么地方订阅,在什么地方观察。
按照我们之前的上下游观点,上游的人抛东西下来,下游的人接住。那么很显然下游的人肯定是观察的人,这个毋庸置疑。那么相应的上游的人就是订阅者(实际上订阅者还是太费解,我们把它理解成抛东西的人)
那么这两个方法现在按照我们的理解就是在哪里抛东西,和在哪里观察。
OK,我们来看一下这两个方法的传参,都是
Scheduler
。点进去一看。。。。抽象类。。不能直接用了。。。跪了。。
完。。。。
- #####再探
就这么结束了??开玩笑!!
还记得在第一篇中,我们不知道什么东西跟Subscriber一起连用的时候我们怎么做来着!没错!!github,源码目录走起。
我们在根目录下发现schedulers目录,打开,看到Schedulers.java文件,点开来一看- #####再探
public final class Schedulers { @NonNull static final Scheduler SINGLE; @NonNull static final Scheduler COMPUTATION; @NonNull static final Scheduler IO; @NonNull static final Scheduler TRAMPOLINE; @NonNull static final Scheduler NEW_THREAD; ...}
给了我们五个静态类,虽然看了一下,它似乎又在类中维护了这五个Scheduler的单例,但是毕竟是protected的不能直接给哥们儿拿来用啊。
然后一不小心,接着往下看的时候发现了,公有的静态方法,并且返回的还是我们正好需要的Scheduler,我去:
//处理iopublic static Scheduler io() //处理复杂计算public static Scheduler computation() //普通的单独线程public static Scheduler single() //新起一个线程public static Scheduler newThread()//在当前线程中,但是会等到当前线程任务执行完毕之后再去执行public static Scheduler trampoline()
相应的注释,我也差不多备注在方法上。
于是我们对我们的代码做一定的改动,然后打上相应的log
flowable.subscribeOn(Schedulers.single()).observeOn(Schedulers.newThread()).subscribe(subscriber);//当前线程名Thread.currentThread().getName()
如果你不知道这段代码是获得当前线程的名字,那要么出门左转java线程基础,要么ctrl + W。。。。
我们发现答应出来的log并没有什么问题,和我们预料的一样
02-22 01:05:19.346 31814-31814/org.ding.testmulti E/subscriber: onSubscribe thread : main02-22 01:05:19.355 31814-4422/org.ding.testmulti E/subscriber: onNext : s hello flowable102-22 01:05:19.355 31814-4422/org.ding.testmulti E/subscriber: onNext thread : RxNewThreadScheduler-102-22 01:05:19.355 31814-4422/org.ding.testmulti E/subscriber: onNext : s hello flowable202-22 01:05:19.355 31814-4422/org.ding.testmulti E/subscriber: onNext thread : RxNewThreadScheduler-102-22 01:05:19.355 31814-4423/org.ding.testmulti E/flowable: thread : RxSingleScheduler-1
subscriber就是我们所说的下游的观察者,由于我们这里使用到的是flowable和subscriber这一对鸳鸯。需要在onSubscribe方法中去调用Subscription的request方法,就很显然的可以理解,在onSubscribe方法中实际上我们还没有开始建立真正的连接,直到request之后我们在onNext,onError,onComplete中才是真正在observerOn的线程中运行的,可以看到两个onNext都是newThread没错。
subscribeOn就是上游的线程,定义在flowable的subscribe中的方法就是运行在我们定义的singleThread没错。
- #####细思
- ######主线程怎么没有
主线程是我们使用最最频繁的线程了,所有的UI操作都要放在我们的主线程中去进行,那设想一下,如果我们需要在上游或者是下游做一些UI操作,当然如果我们没有刻意的去使用SubscribeOn
和ObserverOn
,而我们的subscribe方法又正好在主线程中调用,那没有问题,整个都是在主线程中跑的,要是我们使用了呢,怎么办呢,Schedulers里面并没有提供主线程这个东西啊,没有main
这个东西啊
- ######主线程怎么没有
我又去找github了,目录翻了一圈,也没有找到MainThread这个鬼,好了,这回真放弃,大家再见。。。。
醒了醒神,再回过头想想,主线程这个东西,是否是安卓特地适配的呢,rxjava中怎么可能会出现android特有的东西呢。。。
- ######为我们的rxjava添上Android的模块
说时迟,那时快。。。。(好老)
我们立马前往ReativeX的github库,看到RxGo,RxKotlin(java8来了你颤抖么),再往下,找到了RxAndroid!!
点进去,看目录!!
你没有看错,rxandroid里面只有这些。。。
还正好出现了我们需要的AndroidSchedulers
,赶紧吃饱辣条,点击去看看
/** A {@link Scheduler} which executes actions on the Android main thread. */ public static Scheduler mainThread() { return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);}
还要我说废话么。。。
去module setting里面搜搜看这个dependency,注意哦,rxandroid也有适配rxjava1和rxjava2的两种版本哦,我们使用的是rxjava2的版本
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
上下游的On关系
不知道细心的你有没有去尝试过一个问题,只用subscribeOn和只用observerOn会出现什么情况。
通过打印日志,你会发现如果只定义了上游的线程,而没有定义下游的线程,那么下游的线程将跟随上游的线程;如果只定义了下游的线程,那么上游的线程将依然使用当前线程。
实际上也很好理解,上游发生了海啸洪水必然会影响下游,导致下游也波澜。而下游起了波澜,上游该咋地还咋地。
- Schedulers的几个方法具体区别
我们在上面大体的把几个都解释了一下,但是具体的什么时候用什么呢,我们一一来看- compute
还记的上面说的维护了静态五个Scheduler么,我们看到compute对应的Scheduler是ComputationScheduler
,源码走起!
- compute
- Schedulers的几个方法具体区别
/*** Create a scheduler with pool size equal to the available processor* count and using least-recent worker selection policy.*/public ComputationScheduler() { this(THREAD_FACTORY);}
注释够明显了么,翻译过来大致是说会起一个线程池,大小跟available processor的数量(就是CPU数量)相等,并使用最近的工作线程选择策略。
也就是说,compute方法会用把方法放在一个大小等于CPU核数的线程池中执行。
* single
public SingleScheduler() { this(SINGLE_THREAD_FACTORY);}public SingleScheduler(ThreadFactory threadFactory) { this.threadFactory = threadFactory; executor.lazySet(createExecutor(threadFactory));}static ScheduledExecutorService createExecutor(ThreadFactory threadFactory) { return SchedulerPoolFactory.create(threadFactory);}
我们看到也是创建了一个线程池,我们去create方法继续看,
public static ScheduledExecutorService create(ThreadFactory factory) { final ScheduledExecutorService exec = Executors.newScheduledThreadPool(1, factory); if (exec instanceof ScheduledThreadPoolExecutor) { ScheduledThreadPoolExecutor e = (ScheduledThreadPoolExecutor) exec; POOLS.put(e, exec); } return exec;}public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) { super(corePoolSize, Integer.MAX_VALUE, DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, new DelayedWorkQueue(), threadFactory);}
不知道在android面试实用版2中,大家有否记得,说道的几个线程池,这里用到到就是计划线程池,主要是用来在未来的某一时刻进行执行的线程池,我们看到传入的是1,也就是说single会让方法在核心线程为1的线程池中工作。
* io
public IoScheduler() { this(WORKER_THREAD_FACTORY);}public IoScheduler(ThreadFactory threadFactory) { this.threadFactory = threadFactory; this.pool = new AtomicReference<CachedWorkerPool>(NONE); start();}
使用的一个叫CachedWorkerPool
的内部类,
CachedWorkerPool(long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory) { this.keepAliveTime = unit != null ? unit.toNanos(keepAliveTime) : 0L; this.expiringWorkerQueue = new ConcurrentLinkedQueue<ThreadWorker>(); this.allWorkers = new CompositeDisposable(); this.threadFactory = threadFactory; ScheduledExecutorService evictor = null; Future<?> task = null; if (unit != null) { evictor = Executors.newScheduledThreadPool(1, EVICTOR_THREAD_FACTORY); task = evictor.scheduleWithFixedDelay(this, this.keepAliveTime, this.keepAliveTime, TimeUnit.NANOSECONDS); } evictorService = evictor; evictorTask = task;}
ScheduledThreadPoo线程池,每一个任务相隔60纳秒(好小的样子)。并且维护了一个任务队列
ThreadWorker get() { if (allWorkers.isDisposed()) { return SHUTDOWN_THREAD_WORKER; } while (!expiringWorkerQueue.isEmpty()) { ThreadWorker threadWorker = expiringWorkerQueue.poll(); if (threadWorker != null) { return threadWorker; } } // No cached worker found, so create a new one. ThreadWorker w = new ThreadWorker(threadFactory); allWorkers.add(w); return w;}
可以不断的对任务队列进行处理,可以认为这个队列是无限长的,好了。。这边扯得有点远。。
也就是说io会让方法执行在一个无数量上线的线程池
- newThread
newThreadScheduler的代码是最少的,我们直接可以看到
@NonNull@Overridepublic Worker createWorker() { return new NewThreadWorker(threadFactory);}
每次都会起一个新的线程,也就是说newthread会让方法都在新的线程中执行
* trampoline
如注释。就是在当前线程中执行,并且等当前线程执行完了之后再去执行。
别问我怎么没有源码了,因为我不懂。
那么综上所述,一般我们使用的最多的应该就是主线程和io了,如果你要使用其他的方法,那么具体任务具体分析了。
- 抱着陌生的态度再看Rxjava(二)
- 抱着陌生的态度再看Rxjava(一)
- Android RxJava使用介绍(二) RxJava的操作符
- Android RxJava使用介绍(二) RxJava的操作符
- Android RxJava使用介绍(二) RxJava的操作符
- Android RxJava使用介绍(二) RxJava的操作符
- 开始学习linux内核(抱着兴趣的态度)
- STL学习笔记(二):STL对待错误的态度
- laravel陌生知识点快速学习(二)
- 二、再看看不是PyObject的PyXXXObject
- 等待,抱着积极的态度
- Android RxJava的使用(二)Action
- 【Android】RxJava的使用(二)Action
- 一篇RxJava友好的文章(二)
- 我所理解的RxJava(二)
- 我的RxJava入门(二)
- 【Android】RxJava的使用(二)Action
- RxJava教程(二)
- 直接插入排序
- 浅谈Java中的对象和对象引用
- mycat2.0配置文件datasource.yml参数说明(switchType)
- Vue——渲染(文本、列表)、列表数据更新
- 基于opencv和Tensorflow的实时手势识别(2)
- 抱着陌生的态度再看Rxjava(二)
- 异常
- python中的函数
- tensorflow: 对variable_scope进行reuse的两种方法
- Java基础(4)-循环语句和随机数
- Python入门教程完整版(懂中文就能学会)
- springboot vue 登录页面01 每天进步百分之一
- 常用框架
- 电脑