基于RxJava2.1.1
我们在前面的 RxJava2.0使用详解(一)初步分析了RxJava从创建到执行的流程。也明白了RxJava的onComplete();与onError(t);只有一个会被执行的秘密。
本次我们将探索RxJava2.x线程切换的实现原理。做到知其然,知其所以然。
Ok,开始我们的探索之旅吧!
先来看看没有切换线程的demo:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
e.onNext(123);
Log.d("MainActivity","onNext(发送) :"+ "123");
}
})
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer integer) {
Log.d("MainActivity","onNext(接收) :"+integer + "");
Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
====================================
结果是:
2021-01-23 16:27:02.667 16788-16788/com.damon.myapplication D/MainActivity: 工作线程是:main
2021-01-23 16:27:02.668 16788-16788/com.damon.myapplication D/MainActivity: onNext(发送) :123
2021-01-23 16:27:02.668 16788-16788/com.damon.myapplication D/MainActivity: 工作线程是:main
2021-01-23 16:27:02.668 16788-16788/com.damon.myapplication D/MainActivity: onNext(接收) :123
再来看看有切换线程功能的版本:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
Log.d("MainActivity","onNext(发送) :"+ "123");
e.onNext(123);
}
}).subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
Log.d("MainActivity","onSubscribe :");
}
@Override
public void onNext(Integer integer) {
Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
Log.d("MainActivity","onNext(接收) :"+integer + "");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
=======================================
结果是:
2021-01-25 10:59:51.859 3508-3508/com.damon.myapplication D/MainActivity: 工作线程是:main
2021-01-25 10:59:51.859 3508-3508/com.damon.myapplication D/MainActivity: onSubscribe :
2021-01-25 10:59:51.871 3508-3691/com.damon.myapplication D/MainActivity: 工作线程是:RxCachedThreadScheduler-1
2021-01-25 10:59:51.871 3508-3691/com.damon.myapplication D/MainActivity: onNext(发送) :123
2021-01-25 10:59:51.872 3508-3694/com.damon.myapplication D/MainActivity: 工作线程是:RxCachedThreadScheduler-2
2021-01-25 10:59:51.872 3508-3694/com.damon.myapplication D/MainActivity: onNext(接收) :123
很显然,Observer的onSubsriber()在那个线程调用,就在那个线程执行(此时是在Main线程里调用),发送事件和接收事件都会另外开一个Io线程来执行。
OK,现象看完了,我们开始看本质吧!但是,从哪入手呢?还是老办法,哪里触发的行为就哪里下手( ̄∇ ̄)
OK,我们先来探索切换Observable工作线程的subscribeOn方法入手:
Class Observable{
......
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> subscribeOn(Scheduler scheduler) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}
}
看到了RxJavaPlugins.onAssembly,前面分析过,为hook服务,现在看成是返回传入的Obserable即可。这里的this为我们的observable,scheduler就是我们传入的Schedulers.io();我们继续看ObservableSubscribeOn:
public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {....}
其继承AbstractObservableWithUpstream:
abstract class AbstractObservableWithUpstream<T, U> extends Observable<U> implements HasUpstreamObservableSource<T> {
/** The source consumable Observable. */
protected final ObservableSource<T> source;
/**
* Constructs the ObservableSource with the given consumable. * @param source the consumable Observable
*/ AbstractObservableWithUpstream(ObservableSource<T> source) {
this.source = source;
}
@Override
public final ObservableSource<T> source() {
return source;
}
}
AbstractObservableWithUpstream继承自Observable,其作用是通过source字段保存上游的Observable,因为Observable是ObservableSource接口的实现类,所以我们可以认为Observable和ObservableSource在本文中是相等的:,
也就是说ObservableSubscribeOn是对Observble进行了一次wrapper操作
OK,我们继续回来看ObservableSubscribeOn的源码:
public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
//1、线程调度器
final Scheduler scheduler;
public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
//2、存储上游的obserble
super(source);
this.scheduler = scheduler;
}
@Override
public void subscribeActual(final Observer<? super T> s) {
//以下为关键部分
//3、对我们下游的observer进行一次wrapper
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);
//4、同样,先自己调用自己的onSubscribe
s.onSubscribe(parent);
//5、(高能量聚集了)将调度的线程的Disposable赋值给当前的Disposable。scheduler可以看成是某个线程上的调度器。new SubscribeTask(parent)工作在其指定的线程里面。SubscribeTask是一个Runnable,也就是说调度器触发Runnable的run()运行,
//***是不是恍然大悟,那么run()里面的代码就是运行在scheduler的线程上了。这样也就实现了线程的切换了。
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}
static final class SubscribeOnObserver<T> extends AtomicReference implements Observer<T>, Disposable {....}
...
}
继续看一下ObservableSubscribeOn的内部类SubscribeOnObserver:
static final class SubscribeOnObserver<T> extends AtomicReference<Disposable> implements Observer<T>, Disposable {
private static final long serialVersionUID = 8094547886072529208L;
final Observer<? super T> actual;
final AtomicReference<Disposable> s;
SubscribeOnObserver(Observer<? super T> actual) {
this.actual = actual;
this.s = new AtomicReference<Disposable>();
}
@Override
public void onSubscribe(Disposable s) {
DisposableHelper.setOnce(this.s, s);
}
@Override
public void onNext(T t) {
actual.onNext(t);
}
@Override
public void onError(Throwable t) {
actual.onError(t);
}
@Override
public void onComplete() {
actual.onComplete();
}
@Override
public void dispose() {
DisposableHelper.dispose(s);
DisposableHelper.dispose(this);
}
@Override
public boolean isDisposed() {
return DisposableHelper.isDisposed(get());
}
void setDisposable(Disposable d) {
DisposableHelper.setOnce(this, d);
}
}
SubscribeOnObserver实现了observer,且构造器中传入了一个observer类型的参数,说明这个类主要的作用就是对下游的observer进行一次包装,从重写的方法来看,也证实了这一点,都调用了下游observer里的相对应的方法。
Ok,我们继续看SubscribeTask这个类:
final class SubscribeTask implements Runnable {
private final SubscribeOnObserver<T> parent;
SubscribeTask(SubscribeOnObserver<T> parent) {
this.parent = parent;
}
@Override
public void run() {
source.subscribe(parent);
}
}
parent就是我们包装后的observer,其内部保存了下游的observer
source即通过ObservableSubscribeOnwrapper后存储我们上游的observable
所以run里面的source.subscribe(parent);即为wrapper的observer订阅了上游的observable,触发了上游observable的subscribeActual,开始执行数据的分发。
具体可以下图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210125194618566.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NDMxNDA1,size_16,color_FFFFFF,t_70
思路梳理(重要)
Ok,分析到这里思路基本清晰了
1、在执行subscribeOn时,在Observable和observer中插入了一个(wrapper)obserabler和(wrapper)Observer
原observable->【(Wrapper)observable||(Wrapper)Observer】->(原)Observer
2、observable.subscribe触发->(Wrapper)Observable.subscribeActual()内部调用->parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));,->scheduler在指定线程调用(完成线程切换)->SubscribeTask.run,run内部调用->原Observable.subscribe((Wrapper)Observer)触发->(原)Observable.subscribeActual()开始数据分发
Ok,此时分发给的是(Wrapper)Observer,那应该是(Wrapper)Observer分发给了(原)Observer。
Ok,有了对SubscribeOnObserver分析的铺垫,我们现在可以分析一下
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)))
我们先看scheduler.scheduleDirect()这句
@NonNull
//以毫秒为单位,无延迟调度
public Disposable scheduleDirect(@NonNull Runnable run) {
return scheduleDirect(run, 0L, TimeUnit.NANOSECONDS);
}
其返回一个Disposable,我们看下这个Disposable是否真的是调度的线程的。
@NonNull
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
@NonNull
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
//13、Worker实现了Disposable的一个调度工作者类
final Worker w = createWorker();
//14、hook,排除hook干扰,可以理解为decoratedRun==run
final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
//15、DisposeTask同样是实现了Disposable的Task
DisposeTask task = new DisposeTask(decoratedRun, w);
//16、开始执行
w.schedule(task, delay, unit);
//17、确实是返回了管理run的worker
return task;
}
}
Ok,现在终点转移到DisposeTask,我们把run给了DisposeTask,然后worker调度task开始执行run
OK,那么我们可以猜测w.schedule(task, delay, unit)执行后应该是调度了task的某个方法,然后task开始执行Runnable的run
是不是真的呢?我们来看下new DisposeTask(decoratedRun, w)做了什么
static final class DisposeTask implements Runnable, Disposable {
//18、我们外部传入的runnable
final Runnable decoratedRun;
//19、调度工作者
final Worker w;
//20、当前线程
Thread runner;
DisposeTask(Runnable decoratedRun, Worker w) {
this.decoratedRun = decoratedRun;
this.w = w;
}
@Override
public void run() {
//21、获取执decoratedRun的线程
runner = Thread.currentThread();
try {
//22、OK,高能来了。decoratedRun的run被执行
decoratedRun.run();
} finally {
dispose();
runner = null;
}
}
@Override
public void dispose() {
if (runner == Thread.currentThread() && w instanceof NewThreadWorker) {
((NewThreadWorker)w).shutdown();
} else {
//在DisposeTask被取消时,告诉Worker取消,因为DisposeTask是Worker进行管理的
w.dispose();
}
}
@Override
public boolean isDisposed() {
return w.isDisposed();
}
}
结论:
scheduler.scheduleDirect无延迟调用->worker->worker调度->DisposeTask->DisposeTask.run执行->decoratedRun.run();
decoratedRun即我们外部的SubscribeTask