前言

很多项目使用流行的Rxjava2 + Retrofit搭建网络框架,Rxjava现在已经发展到Rxjava2,之前一直都只是再用Rxjava,但从来没有了解下Rxjava的内部实现,接下来一步步来分析Rxjava2的源码,Rxjava2分Observable和Flowable两种(无被压和有被压),我们今天先从简单的无背压的observable来分析。源码基于rxjava:2.1.1。

一、Rxjava如何创建事件源、发射事件、何时发射事件、如何将观察者和被观察者关联起来

简单的例子

先来段最简单的代码,直观的了解下整个Rxjava运行的完整流程。

 private void doSomeWork() {
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext("a");
e.onComplete();
}
});
Observer observer = new Observer<String>() { @Override
public void onSubscribe(Disposable d) {
Log.i("lx", " onSubscribe : " + d.isDisposed());
} @Override
public void onNext(String str) {
Log.i("lx", " onNext : " + str);
} @Override
public void onError(Throwable e) {
Log.i("lx", " onError : " + e.getMessage());
} @Override
public void onComplete() {
Log.i("lx", " onComplete");
}
};
observable.subscribe(observer);
}

上面代码之所以将observable和observer单独声明,最后再调用observable.subscribe(observer);
是为了分步来分析:

  1. 被观察者 Observable 如何生产事件的
  2. 被观察者 Observable 何时生产事件的
  3. 观察者Observer是何时接收到上游事件的
  4. Observable 与Observer是如何关联在一起的

Observable

Observable是数据的上游,即事件生产者
首先来分析事件是如何生成的,直接看代码 Observable.create()方法。

 @SchedulerSupport(SchedulerSupport.NONE)
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) { // ObservableOnSubscribe 是个接口,只包含subscribe方法,是事件生产的源头。
ObjectHelper.requireNonNull(source, "source is null"); // 判空
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}

最重要的是RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));这句代码。继续跟踪进去

 /**
* Calls the associated hook function.
* @param <T> the value type
* @param source the hook's input value
* @return the value returned by the hook
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@NonNull
public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
Function<? super Observable, ? extends Observable> f = onObservableAssembly;
if (f != null) {
return apply(f, source);
}
return source;
}

看注释,原来这个方法是个hook function。 通过调试得知静态对象onObservableAssembly默认为null, 所以此方法直接返回传入的参数source。
onObservableAssembly可以通过静态方法RxJavaPlugins. setOnObservableAssembly ()设置全局的Hook函数, 有兴趣的同学可以自己去试试。 这里暂且不谈,我们继续返回代码。
现在我们明白了:

  Observable<String> observable=Observable.create(new ObservableOnSubscribe<String>() {
  ...
  ...
})

相当于:

 Observable<String> observable=new ObservableCreate(new ObservableOnSubscribe<String>() {
  ...
  ...
}))

好了,至此我们明白了,事件的源就是new ObservableCreate()对象,将ObservableOnSubscribe作为参数传递给ObservableCreate的构造函数。
事件是由接口ObservableOnSubscribe的subscribe方法上产的,至于何时生产事件,稍后再分析。

Observer

Observer 是数据的下游,即事件消费者
Observer是个interface,包含 :

     void onSubscribe(@NonNull Disposable d);
void onNext(@NonNull T t);
void onError(@NonNull Throwable e);
void onComplete();

上游发送的事件就是再这几个方法中被消费的。上游何时发送事件、如何发送,稍后再表。

subscribe

重点来了,接下来最重要的方法来了:observable.subscribe(observer);
从这个方法的名字就知道,subscribe是订阅,是将观察者(observer)与被观察者(observable)连接起来的方法。只有subscribe方法执行后,上游产生的事件才能被下游接收并处理。其实自然的方式应该是observer订阅(subscribe) observable, 但这样会打断rxjava的链式结构。所以采用相反的方式。
接下来看源码,只列出关键代码

 public final void subscribe(Observer<? super T> observer) {
ObjectHelper.requireNonNull(observer, "observer is null");
......
observer = RxJavaPlugins.onSubscribe(this, observer); // hook ,默认直接返回observer
......
subscribeActual(observer); // 这个才是真正实现订阅的方法。
......
} // subscribeActual 是抽象方法,所以需要到实现类中去看具体实现,也就是说实现是在上文中提到的ObservableCreate中
protected abstract void subscribeActual(Observer<? super T> observer);

接下来我们来看ObservableCreate.java:

 public ObservableCreate(ObservableOnSubscribe<T> source) {
this.source = source; // 事件源,生产事件的接口,由我们自己实现
} @Override
protected void subscribeActual(Observer<? super T> observer) {
CreateEmitter<T> parent = new CreateEmitter<T>(observer); // 发射器
observer.onSubscribe(parent); //直接回调了观察者的onSubscribe try {
// 调用了事件源subscribe方法生产事件,同时将发射器传给事件源。
// 现在我们明白了,数据源生产事件的subscribe方法只有在observable.subscribe(observer)被执行
后才执行的。 换言之,事件流是在订阅后才产生的。
//而observable被创建出来时并不生产事件,同时也不发射事件。
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}

现在我们明白了,数据源生产事件的subscribe方法只有在observable.subscribe(observer)被执行后才执行的。 换言之,事件流是在订阅后才产生的。而observable被创建出来时并不生产事件,同时也不发射事件。
接下来我们再来看看事件是如何被发射出去,同时observer是如何接收到发射的事件的
CreateEmitter<T> parent = new CreateEmitter<T>(observer);
CreateEmitter 实现了ObservableEmitter接口,同时ObservableEmitter接口又继承了Emitter接口。
CreateEmitter 还实现了Disposable接口,这个disposable接口是用来判断是否中断事件发射的。
从名称上就能看出,这个是发射器,故名思议是用来发射事件的,正是它将上游产生的事件发射到下游的。
Emitter是事件源与下游的桥梁。
CreateEmitter 主要包括方法:

 void onNext(@NonNull T value);
void onError(@NonNull Throwable error);
void onComplete();
public void dispose() ;
public boolean isDisposed();

是不是跟observer的方法很像?
我们来看看CreateEmitter中这几个方法的具体实现:
只列出关键代码

 public void onNext(T t) {
if (!isDisposed()) { // 判断事件是否需要被丢弃
observer.onNext(t); // 调用Emitter的onNext,它会直接调用observer的onNext
}
}
public void onError(Throwable t) {
if (!isDisposed()) {
try {
observer.onError(t); // 调用Emitter的onError,它会直接调用observer的onError
} finally {
dispose(); // 当onError被触发时,执行dispose(), 后续onNext,onError, onComplete就不会继
续发射事件了
}
}
} @Override
public void onComplete() {
if (!isDisposed()) {
try {
observer.onComplete(); // 调用Emitter的onComplete,它会直接调用observer的onComplete
} finally {
dispose(); // 当onComplete被触发时,也会执行dispose(), 后续onNext,onError, onComplete
同样不会继续发射事件了
}
}
}

CreateEmitter 的onError和onComplete方法任何一个执行完都会执行dispose()中断事件发射,所以observer中的onError和onComplete也只能有一个被执行。
现在终于明白了,事件是如何被发射给下游的。当订阅成功后,数据源ObservableOnSubscribe开始生产事件,调用Emitter的onNext,onComplete向下游发射事件,

Emitter包含了observer的引用,又调用了observer onNext,onComplete,这样下游observer就接收到了上游发射的数据。

总结

Rxjava的流程大概是:

  1. Observable.create 创建事件源,但并不生产也不发射事件。
  2. 实现observer接口,但此时没有也无法接受到任何发射来的事件。
  3. 订阅 observable.subscribe(observer), 此时会调用具体Observable的实现类中的subscribeActual方法,
    此时会才会真正触发事件源生产事件,事件源生产出来的事件通过Emitter的onNext,onError,onComplete发射给observer对应的方法由下游observer消费掉。从而完成整个事件流的处理。

observer中的onSubscribe在订阅时即被调用,并传回了Disposable, observer中可以利用Disposable来随时中断事件流的发射。

今天所列举的例子是最简单的一个事件处理流程,没有使用线程调度,Rxjava最强大的就是异步时对线程的调度和随时切换观察者线程,未完待续。

上面分析了Rxjava是如何创建事件源,如何发射事件,何时发射事件,也清楚了上游和下游是如何关联起来的。
下面着重来分析下Rxjava强大的线程调度是如何实现的。

二、RxJava的线程调度机制

简单的例子

 private void doSomeWork() {
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
Log.i("lx", " subscribe: " + Thread.currentThread().getName());
Thread.sleep(2000);
e.onNext("a");
e.onComplete();
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.i("lx", " onSubscribe: " + Thread.currentThread().getName());
}
@Override
public void onNext(String str) {
Log.i("lx", " onNext: " + Thread.currentThread().getName());
}
@Override
public void onError(Throwable e) {
Log.i("lx", " onError: " + Thread.currentThread().getName());
}
@Override
public void onComplete() {
Log.i("lx", " onComplete: " + Thread.currentThread().getName());
}
});
}

运行结果:

 com.rxjava2.android.samples I/lx:  onSubscribe: main
com.rxjava2.android.samples I/lx: subscribe: main
com.rxjava2.android.samples I/lx: onNext: main
com.rxjava2.android.samples I/lx: onComplete: main

因为此方法笔者是在main线程中调用的,所以没有进行线程调度的情况下,所有方法都运行在main线程中。但我们知道Android的UI线程是不能做网络操作,也不能做耗时操作,所以一般我们把网络或耗时操作都放在非UI线程中执行。接下来我们就来感受下Rxjava强大的线程调度能力。

 private void doSomeWork() {
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
Log.i("lx", " subscribe: " + Thread.currentThread().getName());
Thread.sleep(2000);
e.onNext("a");
e.onComplete();
}
}).subscribeOn(Schedulers.io()) //增加了这一句
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.i("lx", " onSubscribe: " + Thread.currentThread().getName());
}
@Override
public void onNext(String str) {
Log.i("lx", " onNext: " + Thread.currentThread().getName());
}
@Override
public void onError(Throwable e) {
Log.i("lx", " onError: " + Thread.currentThread().getName());
}
@Override
public void onComplete() {
Log.i("lx", " onComplete: " + Thread.currentThread().getName());
}
});
}

运行结果:

 com.rxjava2.android.samples I/lx:  onSubscribe: main
com.rxjava2.android.samples I/lx: subscribe: RxCachedThreadScheduler-1
com.rxjava2.android.samples I/lx: onNext: RxCachedThreadScheduler-1
com.rxjava2.android.samples I/lx: onComplete: RxCachedThreadScheduler-1

只增加了subscribeOn这一句代码, 就发生如此神奇的现象,除了onSubscribe方法还运行在main线程(订阅发生的线程)其它方法全部都运行在一个名为RxCachedThreadScheduler-1的线程中。我们来看看rxjava是怎么完成这个线程调度的。

线程调度subscribeOn

首先我们先分析下Schedulers.io()这个东东。

  @NonNull
public static Scheduler io() {
return RxJavaPlugins.onIoScheduler(IO); // hook function
// 等价于
return IO;
}

再看看IO是什么, IO是个static变量,初始化的地方是

 IO = RxJavaPlugins.initIoScheduler(new IOTask()); // 又是hook function
// 等价于
IO = callRequireNonNull(new IOTask());
// 等价于
IO = new IOTask().call();

继续看看IOTask

 static final class IOTask implements Callable<Scheduler> {
@Override
public Scheduler call() throws Exception {
return IoHolder.DEFAULT;
// 等价于
return new IoScheduler();
}
}

代码层次很深,为了便于记忆,我们再回顾一下:

 Schedulers.io()等价于 new IoScheduler()

     // Schedulers.io()等价于
@NonNull
public static Scheduler io() {
return new IoScheduler();
}

好了,排除了其他干扰代码,接下来看看IoScheduler()是什么东东了

IoScheduler看名称就知道是个IO线程调度器,根据代码注释得知,它就是一个用来创建和缓存线程的线程池。看到这个豁然开朗了,原来Rxjava就是通过这个调度器来调度线程的,至于具体怎么实现我们接着往下看

 public IoScheduler() {
this(WORKER_THREAD_FACTORY);
} public IoScheduler(ThreadFactory threadFactory) {
this.threadFactory = threadFactory;
this.pool = new AtomicReference<CachedWorkerPool>(NONE);
start();
} @Override
public void start() {
CachedWorkerPool update = new CachedWorkerPool(KEEP_ALIVE_TIME, KEEP_ALIVE_UNIT, threadFactory);
if (!pool.compareAndSet(NONE, update)) {
update.shutdown();
}
} 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;
}

从上面的代码可以看出,new IoScheduler()后Rxjava会创建CachedWorkerPool的线程池,同时也创建并运行了一个名为RxCachedWorkerPoolEvictor的清除线程,主要作用是清除不再使用的一些线程。

但目前只创建了线程池并没有实际的thread,所以Schedulers.io()相当于只做了线程调度的前期准备。

OK,终于可以开始分析Rxjava是如何实现线程调度的。回到Demo来看subscribeOn()方法的内部实现:

 public final Observable<T> subscribeOn(Scheduler scheduler) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}

很熟悉的代码RxJavaPlugins.onAssembly,上一篇已经分析过这个方法,就是个hook function, 等价于直接return new ObservableSubscribeOn<T>(this, scheduler);, 现在知道了这里的scheduler其实就是IoScheduler。

跟踪代码进入ObservableSubscribeOn
可以看到这个ObservableSubscribeOn 继承自Observable,并且扩展了一些属性,增加了scheduler。 各位看官,这不就是典型的装饰模式嘛,Rxjava中大量用到了装饰模式,后面还会经常看到这种wrap类。

上篇文章我们已经知道了Observable.subscribe()方法最终都是调用了对应的实现类的subscribeActual方法。我们重点分析下subscribeActual:

 @Override
public void subscribeActual(final Observer<? super T> s) {
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s); // 没有任何线程调度,直接调用的,所以下游的onSubscribe方法没有切换线程,
//本文demo中下游就是观察者,所以我们明白了为什么只有onSubscribe还运行在main线程
s.onSubscribe(parent); parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}

SubscribeOnObserver也是装饰模式的体现, 是对下游observer的一个wrap,只是添加了Disposable的管理。

接下来分析最重要的scheduler.scheduleDirect(new SubscribeTask(parent))

 // 这个类很简单,就是一个Runnable,最终运行上游的subscribe方法
final class SubscribeTask implements Runnable {
private final SubscribeOnObserver<T> parent; SubscribeTask(SubscribeOnObserver<T> parent) {
this.parent = parent;
} @Override
public void run() {
source.subscribe(parent);
}
}
@NonNull
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
// IoSchedular 中的createWorker()
final Worker w = createWorker();
// hook decoratedRun=run;
final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
// decoratedRun的wrap,增加了Dispose的管理
DisposeTask task = new DisposeTask(decoratedRun, w);
// 线程调度
w.schedule(task, delay, unit); return task;
}

回到IoSchedular

 public Worker createWorker() {
// 工作线程是在此时创建的
return new EventLoopWorker(pool.get());
} public Disposable schedule(@NonNull Runnable action, long delayTime, @NonNull TimeUnit unit) {
if (tasks.isDisposed()) {
// don't schedule, we are unsubscribed
return EmptyDisposable.INSTANCE;
}
// action 中就包含上游subscribe的runnable
return threadWorker.scheduleActual(action, delayTime, unit, tasks);
}

最终线程是在这个方法内调度并执行的。

 public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
// decoratedRun = run, 包含上游subscribe方法的runnable
Runnable decoratedRun = RxJavaPlugins.onSchedule(run); // decoratedRun的wrap,增加了dispose的管理
ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent); if (parent != null) {
if (!parent.add(sr)) {
return sr;
}
} // 最终decoratedRun被调度到之前创建或从线程池中取出的线程,
// 也就是说在RxCachedThreadScheduler-x运行
Future<?> f;
try {
if (delayTime <= 0) {
f = executor.submit((Callable<Object>)sr);
} else {
f = executor.schedule((Callable<Object>)sr, delayTime, unit);
}
sr.setFuture(f);
} catch (RejectedExecutionException ex) {
if (parent != null) {
parent.remove(sr);
}
RxJavaPlugins.onError(ex);
} return sr;
}

至此我们终于明白了Rxjava是如何调度线程并执行的,通过subscribeOn方法将上游生产事件的方法运行在指定的调度线程中。

 com.rxjava2.android.samples I/lx:  onSubscribe: main
com.rxjava2.android.samples I/lx: subscribe: RxCachedThreadScheduler-1
com.rxjava2.android.samples I/lx: onNext: RxCachedThreadScheduler-1
com.rxjava2.android.samples I/lx: onComplete: RxCachedThreadScheduler-1

从上面的运行结果来看,因为上游生产者已被调度到RxCachedThreadScheduler-1线程中,同时发射事件并没有切换线程,所以发射后消费事件的onNext onErro onComplete也在RxCachedThreadScheduler-1线程中。

总结

  1. Schedulers.io()等价于 new IoScheduler()。
  2. new IoScheduler() Rxjava创建了线程池,为后续创建线程做准备,同时创建并运行了一个清理线程RxCachedWorkerPoolEvictor,定期执行清理任务。
  3. subscribeOn()返回一个ObservableSubscribeOn对象,它是Observable的一个装饰类,增加了scheduler
  4. 调用subscribe()方法,在这个方法调用后,subscribeActual()被调用,才真正执行了IoSchduler中的createWorker()创建线程并运行,最终将上游Observablesubscribe()方法调度到新创建的线程中运行。

现在了解了被观察者执行线程是如何被调度到指定线程中执行的,但很多情况下,我们希望观察者(事件下游)处理事件最好在UI线程执行,比如更新UI操作等。下面分析下游何时调度,如何调度由于篇幅问题。

三、Rxjava如何对观察者线程进行调度

简单的例子

 private void doSomeWork() {
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
Log.i("lx", " subscribe: " + Thread.currentThread().getName());
e.onNext("a");
e.onComplete();
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.i("lx", " onSubscribe: " + Thread.currentThread().getName());
}
@Override
public void onNext(String str) {
Log.i("lx", " onNext: " + Thread.currentThread().getName());
}
@Override
public void onError(Throwable e) {
Log.i("lx", " onError: " + Thread.currentThread().getName());
}
@Override
public void onComplete() {
Log.i("lx", " onComplete: " + Thread.currentThread().getName());
}
});
}

看看运行结果:

 com.rxjava2.android.samples I/lx:  onSubscribe: main
com.rxjava2.android.samples I/lx: subscribe: RxCachedThreadScheduler-1
com.rxjava2.android.samples I/lx: onNext: main
com.rxjava2.android.samples I/lx: onComplete: main

从结果可以看出,事件的生产线程运行在RxCachedThreadScheduler-1中,而事件的消费线程则被调度到了main线程中。关键代码是因为这句.observeOn(AndroidSchedulers.mainThread())。 下面我们着重分析下这句代码都做了哪些事情。

AndroidSchedulers.mainThread()

先来看看AndroidSchedulers.mainThread()是什么?贴代码

  /** A {@link Scheduler} which executes actions on the Android main thread. */
public static Scheduler mainThread() {
return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);
}

注释已经说的很明白了,是一个在主线程执行任务的scheduler,接着看

 private static final Scheduler MAIN_THREAD = RxAndroidPlugins.initMainThreadScheduler(
new Callable<Scheduler>() {
@Override public Scheduler call() throws Exception {
return MainHolder.DEFAULT;
}
}); public static Scheduler initMainThreadScheduler(Callable<Scheduler> scheduler) {
if (scheduler == null) {
throw new NullPointerException("scheduler == null");
}
Function<Callable<Scheduler>, Scheduler> f = onInitMainThreadHandler;
if (f == null) {
return callRequireNonNull(scheduler);
}
return applyRequireNonNull(f, scheduler);
}

代码很简单,这个AndroidSchedulers.mainThread()想当于new HandlerScheduler(new Handler(Looper.getMainLooper())),原来是利用AndroidHandler来调度到main线程的。

我们再看看HandlerScheduler,它与我们上节分析的IOScheduler类似,都是继承自Scheduler,所以AndroidSchedulers.mainThread()其实就是是创建了一个运行在main thread上的scheduler。
好了,我们再回过头来看observeOn方法。

observeOn

 public final Observable<T> observeOn(Scheduler scheduler) {
return observeOn(scheduler, false, bufferSize());
} public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
ObjectHelper.verifyPositive(bufferSize, "bufferSize");
return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
}

重点是这个new ObservableObserveOn,看名字是不是有种似成相识的感觉,还记得上篇的ObservableSubscribeOn吗? 它俩就是亲兄弟,是继承自同一个父类。

重点还是这个方法,我们前文已经提到了,Observable的subscribe方法最终都是调用subscribeActual方法。下面看看这个方法的实现:

   @Override
protected void subscribeActual(Observer<? super T> observer) {
// scheduler 就是前面提到的 HandlerScheduler,所以进入else分支
if (scheduler instanceof TrampolineScheduler) {
source.subscribe(observer);
} else {
// 创建 HandlerWorker
Scheduler.Worker w = scheduler.createWorker();
// 调用上游Observable的subscribe,将订阅向上传递
source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
}
}

从上面代码可以看到使用了ObserveOnObserver类对observer进行装饰,好了,我们再来看看ObserveOnObserver

我们已经知道了,事件源发射的事件,是通过observer的onNext,onError,onComplete发射到下游的。所以看看ObserveOnObserver的这三个方法是如何实现的。
由于篇幅问题,我们只分析onNext方法,onErroronComplete方法有兴趣的同学可以自己分析下。

 @Override
public void onNext(T t) {
if (done) {
return;
} // 如果是非异步方式,将上游发射的时间加入到队列
if (sourceMode != QueueDisposable.ASYNC) {
queue.offer(t);
}
schedule();
} void schedule() {
// 保证只有唯一任务在运行
if (getAndIncrement() == 0) {
// 调用的就是HandlerWorker的schedule方法
worker.schedule(this);
}
} @Override
public Disposable schedule(Runnable run, long delay, TimeUnit unit) {
if (run == null) throw new NullPointerException("run == null");
if (unit == null) throw new NullPointerException("unit == null"); if (disposed) {
return Disposables.disposed();
} run = RxJavaPlugins.onSchedule(run); ScheduledRunnable scheduled = new ScheduledRunnable(handler, run); Message message = Message.obtain(handler, scheduled);
message.obj = this; // Used as token for batch disposal of this worker's runnables. handler.sendMessageDelayed(message, Math.max(0L, unit.toMillis(delay))); // Re-check disposed state for removing in case we were racing a call to dispose().
if (disposed) {
handler.removeCallbacks(scheduled);
return Disposables.disposed();
} return scheduled;
}

schedule方法将传入的run调度到对应的handle所在的线程来执行,这个例子里就是有main线程来完成。 再回去看看前面传入的run吧。

回到ObserveOnObserver中的run方法:

 @Override
public void run() {
// 此例子中代码不会进入这个分支,至于这个drainFused是什么,后面章节再讨论。
if (outputFused) {
drainFused();
} else {
drainNormal();
}
} void drainNormal() {
int missed = 1; final SimpleQueue<T> q = queue;
final Observer<? super T> a = actual; for (;;) {
if (checkTerminated(done, q.isEmpty(), a)) {
return;
} for (;;) {
boolean d = done;
T v; try {
// 从队列中queue中取出事件
v = q.poll();
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
s.dispose();
q.clear();
a.onError(ex);
worker.dispose();
return;
}
boolean empty = v == null; if (checkTerminated(d, empty, a)) {
return;
} if (empty) {
break;
}
//调用下游observer的onNext将事件v发射出去
a.onNext(v);
} missed = addAndGet(-missed);
if (missed == 0) {
break;
}
}
}

至此我们明白了RXjava是如何调度消费者线程了。

消费者线程调度流程概括

Rxjava调度消费者现在的流程,以observeOn(AndroidSchedulers.mainThread())为例。

  1. AndroidSchedulers.mainThread()先创建一个包含handlerScheduler, 这个handler是主线程的handler
  2. observeOn方法创建ObservableObserveOn,它是上游Observable的一个装饰类,其中包含前面创建的SchedulerbufferSize等.
  3. 当订阅方法subscribe被调用后,ObservableObserveOnsubscribeActual方法创建Scheduler.Worker并调用上游的subscribe方法,同时将自身接收的参数'observer'用装饰类ObserveOnObserver装饰后传递给上游。
  4. 当上游调用被ObserveOnObserveronNextonErroronComplete方法时,ObserveOnObserver将上游发送的事件通通加入到队列queue中,然后再调用scheduler将处理事件的方法调度到对应的线程中(本例会调度到main thread)。 处理事件的方法将queue中保存的事件取出来,调用下游原始的observer再发射出去。
  5. 经过以上流程,下游处理事件的消费者线程就运行在了observeOn调度后的thread中。

总结

经过前面两节的分析,我们已经明白了Rxjava是如何对线程进行调度的。

  • Rxjava的subscribe方法是由下游一步步向上游进行传递的。会调用上游的subscribe,直到调用到事件源。
    如: source.subscribe(xxx);

而上游的source往往是经过装饰后的Observable, Rxjava就是利用ObservableSubscribeOnsubscribe方法调度到了指定线程运行,生产者线程最终会运行在被调度后的线程中。但多次调用subscribeOn方法会怎么样呢? 我们知道因为subscribe方法是由下而上传递的,所以事件源的生产者线程最终都只会运行在第一次执行subscribeOn所调度的线程中,换句话就是多次调用subscribeOn方法,只有第一次有效。

  • Rxjava发射事件是由上而下发射的,上游的onNextonErroronComplete方法会调用下游传入的observer的对应方法。往往下游传递的observer对象也是经过装饰后的observer对象。Rxjava就是利用ObserveOnObserver将执行线程调度后,再调用下游对应的onNextonErroronComplete方法,这样下游消费者就运行再了指定的线程内。 那么多次调用observeOn调度不同的线程会怎么样呢? 因为事件是由上而下发射的,所以每次用observeOn切换完线程后,对下游的事件消费都有效,比如下游的map操作符。最终的事件消费线程运行在最后一个observeOn切换后线程中。
  • 另外通过源码可以看到onSubscribe运行在subscribe的调用线程中,这个就不具体分析了。

RxJava2 源码分析的更多相关文章

  1. RxJava2 中多种取消订阅 dispose 的方法梳理( 源码分析 )

    Github 相关代码: Github地址 一直感觉 RxJava2 的取消订阅有点混乱, 这样也能取消, 那样也能取消, 没能系统起来的感觉就像掉进了盘丝洞, 迷乱… 下面说说这几种情况 几种取消的 ...

  2. RxJava2 源码解析(二)

    概述 承接上一篇RxJava2 源码解析(一),本系列我们的目的: 知道源头(Observable)是如何将数据发送出去的.    知道终点(Observer)是如何接收到数据的.    何时将源头和 ...

  3. RxJava 2.x 源码分析

    本次分析的 RxJava 版本信息如下: 12 implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'implementation 'io.reac ...

  4. RxJava2源码解析(二)

    title: RxJava2源码解析(二) categories: 源码解析 tags: 源码解析 rxJava2 前言 本篇主要解析RxJava的线程切换的原理实现 subscribeOn 首先, ...

  5. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  6. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

  7. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

  8. zookeeper源码分析之五服务端(集群leader)处理请求流程

    leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...

  9. zookeeper源码分析之四服务端(单机)处理请求流程

    上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...

随机推荐

  1. Haskell语言学习笔记(64)Lens(4)

    安装 lens-tutorial Control.Lens.Tutorial $ cabal install lens-tutorial Installed lens-tutorial-1.0.3 P ...

  2. Java Magic. Part 2: 0xCAFEBABE

    Java Magic. Part 2: 0xCAFEBABE @(Base)[JDK, magic, 黑魔法] 转载请写明:原文地址 英文原文 系列文章: -Java Magic. Part 1: j ...

  3. hibernate事务隔离机制

    事务的基本概念 ACID:A是atomicity(原子性),C是consistency(一致性),I是isolation(隔离性),D是durability(持久性) 事务隔离级别从低到高: 读取未提 ...

  4. Mysql一些记忆

    mysql修改密码报错是yum 安装mysql5.7 是 出现无法登陆问题以及mysql error You must reset your password using ALTER USER sta ...

  5. 关于HSTS安全协议的全面详细解析

    HTTP 严格传输安全(HSTS)是一种安全功能,web 服务器通过它来告诉浏览器仅用 HTTPS 来与之通讯,而不是使用 HTTP.HSTS是网站从HTTP到HTTPS中网站性能及安全优化非常重要的 ...

  6. wordpress 下载主题模板、更新报错 No working transports found解决办法

    出错原因是PHP没有开启curl. windows下开启方法如下 1. 将php.ini中的;extension=php_curl.dll前的分号去掉, 2. 将php中libeay32.ll, ss ...

  7. Poor Warehouse Keeper

    Poor Warehouse Keeper http://acm.hdu.edu.cn/showproblem.php?pid=4803 Jenny is a warehouse keeper. He ...

  8. MonkeyRunner原理初步--Android自动化测试学习历程

    章节:自动化基础篇——MonkeyRunner原理初步 主要讲解内容及笔记: 一.理论知识和脚本演示 最佳方式是上官网文档去查看monkeyrunner的介绍,官网上不去,就找了一个本地的androi ...

  9. 删除排序数组中的重复数字 II · Remove Duplicates from Sorted Array II

    重复一次 [抄题]: 给定一个排序数组,在原数组中删除重复出现的数字,使得每个元素只出现一次,并且返回新的数组的长度. 不要使用额外的数组空间,必须在原地没有额外空间的条件下完成. [思维问题]: [ ...

  10. 启动apache时,出现httpd: Could not reliably determine the server\'s fully qualified domain name, using 127.0.0.1 for ServerName

    1.通过vi打开apache的配置文件httpd.conf > vi /data/apache/conf/httpd.conf 2.找到#ServerName www.example.com:8 ...