java子线程切换到主线程_RxJava 是如何实现线程切换的(上)

本文深入解析了RxJava如何实现线程切换,重点介绍了subscribeOn方法的内部实现,包括从创建子线程、启动子线程到上游事件在子线程执行的完整过程。通过对源码的分析,揭示了线程切换的关键步骤,如创建Worker、调度任务、执行Runnable等。文章还提及了Disposable接口在控制上游事件发送中的作用。
摘要由CSDN通过智能技术生成

前言

通过前一篇的从观察者模式出发,聊聊RxJava,我们大致理解了RxJava的实现原理,在RxJava中可以非常方便的实现不同线程间的切换。subscribeOn 用于指定上游线程,observeOn 用于指定下游线程,多次用 subscribeOn 指定上游线程只有第一次有效,多次用 observeOn 指定下次线程,每次都有效;简直太方便了,比直接使用Handler省了不少力气,同时也不用去关注内存泄漏的问题了。本篇就来看看在RxJava中上游是如何实现线程切换。

RxJava 基础原理

为了方便后面的叙述,这里通过下面的UML图简单回顾一下上一篇的内容。

3dd582bb10cc

此图并没有完整的展现图中各个接口和类之间的各种关系,因为那样会导致整个图错综复杂,不便于查看,这里只绘制出了RxJava各个类之间核心关系网络

从上面的UML图中可以看出,具体的实现类只有ObservableCreate和CreateEmitter。CreateEmitter是ObservableCreate的内部类(PlantUML 怎么绘制内部类,没搞懂,玩的转的同学请赐教呀(▽))。

上篇说过Observable创建的过程,可以简化如下:

Observable mObservable=new ObservableCreate(new ObservableOnSubscribe())

结合图可以更直观的体现出这一点。ObservableCreate 内部持有ObservableOnSubscribe的引用。

当观察者订阅主题后:

mObservable.subscribe(mObserver);

ObservableCreate 中的subscribeActual()方法就会执行,

protected void subscribeActual(Observer super T> observer) {

CreateEmitter parent = new CreateEmitter(observer);

observer.onSubscribe(parent);

try {

source.subscribe(parent);

} catch (Throwable ex) {

Exceptions.throwIfFatal(ex);

parent.onError(ex);

}

}

在这个过程中会创建CreateEmitter 的实例,而这个CreateEmitter实现了Emitter和Disposable接口,同时又持有Observer的引用(当然这个引用是ObservableCreate传递给他的)。接着就会执行ObservableOnSubscribe的subscribe 方法,方法的参数即为刚刚创建的CreateEmitter 的实例,接着一系列连锁反应,Emitter 接口中的方法(onNext,onComplete等)开始执行,在CreateEmitter内部,Observer接口中对应的方法依次执行,这样就实现了一次从主题(上游)到观察者(下游)的事件传递。

source.subscribe(parent)

这里的 source 是ObservableOnSubscribe的实例,parent是CreateEmitter的实例。上面加粗文本叙述的内容,就是这行代码,可以说这是整个订阅过程最核心的实现。

好了,回顾完基础知识后,马上进入正题,看看RxJava是如何实现线程切换的。

RxJava 之 subscribeOn

我们知道正常情况下,所有的内容都是在主线程执行,既然这里提到了线程切换,那么必然是切换到了子线程,因此,这里需要关注线程的问题,我们就带着下面这几个问题去阅读代码。

1.是哪个对象在什么时候创建了子线程,是一种怎样的方式创建的?

2.子线程又是如何启动的?

3.上游事件是怎么跑到子线程里执行的?

4.多次用 subscribeOn 指定上游线程为什么只有第一次有效 ?

示例

首先看一下,日常开发中实现线程切换的具体实现

private void multiThread() {

Observable.create(new ObservableOnSubscribe() {

@Override

public void subscribe(ObservableEmitter e) throws Exception {

e.onNext("This msg from work thread :" + Thread.currentThread().getName());

sb.append("\nsubscribe: currentThreadName==" + Thread.currentThread().getName());

}

})

.subscribeOn(Schedulers.newThread())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(new Consumer() {

@Override

public void accept(String s) throws Exception {

Log.e(TAG, "accept: s= " + s);

}

});

}

这段代码,使用过RxJava的同学再熟悉不过了,上游事件会在一个名为 RxNewThreadScheduler-1 的线程执行,下游线程会切换回我们熟悉的Android UI线程。

我们就从subscribeOn(Schedulers.newThread()) 出发,看看这个代码的背后,到底发生了什么。

3dd582bb10cc

subscribeOn

这里我们先不管Schedulers.newThread() 是什么鬼,首先看看这个subscribeOn()方法。

Observable.java--- subscribeOn(Scheduler scheduler)

public final Observable subscribeOn(Scheduler scheduler) {

ObjectHelper.requireNonNull(scheduler, "scheduler is null");

return RxJavaPlugins.onAssembly(new ObservableSubscribeOn(this, scheduler));

}

可以看到,这个方法需要一个Scheduler 类型的参数。

RxJavaPlugins.java--- onAssembly(@NonNull Observable source)

public static Observable onAssembly(@NonNull Observable source) {

Function super Observable, ? extends Observable> f = onObservableAssembly;

if (f != null) {

retu

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值