简介
RxJava的核心是异步;Schedulers实现发射和接收事件在两种不同的线程中去执行相应的操作; 调度器(Schedulers )是RxJava中最重要的一部分,随意的切换调用线程;
Schedulers在RxJava中主要有一下几种方式:
SingleScheduler:共享的,单一线程的调度器;内部有一个核心线程数为1,最大线程数为Integer.MAX的线程池;
ComputationScheduler:计算调度器;内部有一个固定线程池,大小为 CPU 核数;
IoScheduler:Io调度器;内部有一个核心线程数为1,最大线程数为Integer.MAX的线程池;60s的保活时间,保活时间可重复利用;
NewThreadScheduler:新线程调度器;每次都开启一个新线程执行任务;内部有一个核心线程数为1,最大线程数为Integer.MAX的线程池;
TrampolineScheduler:默认情况下,工作在默认的线程;在那个线程发送事件,就在那个线程接收事件,调用不会立即执行,加入队列中,依次执行;
AndroidSchedulers.mainThread():运行在主线程中;通过Handler切换线程;
用法
通过subscribeOn()和observeOn()改变发射事件和接收事件的线程;
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Exception {
Log.e(tag, Thread.currentThread().getName());
for (int i = 0; i < 10; i++) {
emitter.onNext("hello");
Log.e(tag, "newThread() 发送" + Thread.currentThread().getName());
}
}
}).subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.e(tag, "接收::" + Thread.currentThread().getName());
Log.e(tag, s);
}
});
Schedulers线程切换的原理
以上面的代码来分析:
大概的顺序:
1)初始化顺序:ObservableCreate--ObservableSubscribeOn-ObservableObserveOn-LambdaObserver完成初始化;
2)实际的订阅顺序:
2.1)ObservableObserveOn类中的subscribeActual()方法中,创建工作线;ObservableObserveOn订阅(subscribe)ObservableObserveOn类中匿名ObserveOnObserver类,并且将LambdaObserver实例作为参数,传入ObserveOnObserver构造函数;
ObservableObserveOn类
@Override
protected void subscribeActual(Observer<? super T> observer) {
if (scheduler instanceof TrampolineScheduler) {
source.subscribe(observer);
} else {
Scheduler.Worker w = scheduler.createWorker();//创建一个新的调度器
source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));//ObservableObserveOn订阅ObserveOnObserver,并LambdaObserver实例observer
}
}
2.2)在ObservableSubscribeOn类中的subscribeActual方法中,ObserveOnObserver调用onSubscribe()方法,在此方法中LambdaObserver调用onSubscribe(),在此方法中Consumer调用accept(this);
并且在ObservableSubscribeOn类中的subscribeActual中创建task;
ObservableSubscribeOn类,发送事件切换线程的实现过程
@Override
public void subscribeActual(final Observer<? super T> s) {
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);//创建,并传入ObservableObserveOn类的匿名类ObserveOnObserver
s.onSubscribe(parent);//ObserveOnObserver调用onSubscribe(方法)
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));//创建SubscribeTask,切换线程,切换到subscribeOn()中指定的线程;
}
scheduleDirect()方法:在调度任务器上调度给定的任务,支持多线程访问;
@NonNull
public Disposable scheduleDirect(@NonNull Runnable run) {
return scheduleDirect(run, 0L, TimeUnit.NANOSECONDS);
}
scheduleDirect():执行延时任务
@NonNull
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
//Worker抽象类,连续的调度器为了在单个线程或事件循环中执行操作
final Worker w = createWorker();
final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);//onSchedule()方法当task被调度的时候调用
DisposeTask task = new DisposeTask(decoratedRun, w);//相当于一个Runnable,调用decoratedRun的run()方法
w.schedule(task, delay, unit);
return task;
}
NewThreadScheduler类中的createWorker()方法,
public Worker createWorker() {
return new NewThreadWorker(threadFactory);//NewThreadWorker()方法创建一个线程池
}
NewThreadWorker的schedule()方法
@NonNull
@Override
public Disposable schedule(@NonNull final Runnable run) {
return schedule(run, 0, null);
}
@NonNull
@Override
public Disposable schedule(@NonNull final Runnable action, long delayTime, @NonNull TimeUnit unit) {
if (disposed) {
return EmptyDisposable.INSTANCE;
}
return scheduleActual(action, delayTime, unit, null);
}
scheduleActual()把给定的Runnable包装成ScheduledRunnable;并且在线程池调用;
@NonNull
public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
Runnable decoratedRun = RxJavaPlugins.onSchedule(run);//当Task被调度的时候调用
ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);//把给定的Runnable包装成ScheduledRunnable
if (parent != null) {
if (!parent.add(sr)) {
return sr;
}
}
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;
}
发送事件切换线程原理总结:在subscribeActual()方法中创建SubscribeTask,传入scheduleDirect()方法中,在scheduleDirect()调用指定线程的的createWorker()方法,调用NewThreadWorker类创建线程池;worker调用schedule()方法,在schedule()中调用scheduleActual(),在scheduleActual()把给定的Runnable包装成ScheduledRunnable;并且在线程池调用;
在ObservableObserveOn类匿名类ObserveOnObserver的onSubscribe()
@Override
public void onSubscribe(Disposable s) {
//省略中间部分
actual.onSubscribe(this);//LambdaObserver调用onSubscribe(),在此方法中Consumer调用accept(this)
}
SubscribeTask类:ObservableObserveOn的匿名类内部类
final class SubscribeTask implements Runnable {
private final SubscribeOnObserver<T> parent;
SubscribeTask(SubscribeOnObserver<T> parent) {
this.parent = parent;
}
@Override
public void run() {
source.subscribe(parent);//ObservableCreate订阅ObservableSubscribeOn类SubscribeOnObserver
}
}
2.3)ObservableCreate类中subscribeActual()方法中source.subscribe(parent):当前类Observable订阅ObservableCreate类中CreateEmitter;
ObservableCreate类
@Override
protected void subscribeActual(Observer<? super T> observer) {
CreateEmitter<T> parent = new CreateEmitter<T>(observer);//实例化,传入ObservableSubscribeOn类SubscribeOnObserver
observer.onSubscribe(parent);//SubscribeOnObserver执行onSubscribe
try {
source.subscribe(parent);//ObservableOnSubscribe订阅CreateEmitter
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
subscribe():从写法上看是被观察者订阅观察者;只是为了链式写法方便;实际上是观察者订阅被观察者;从上面的分析可以看出来;订阅顺序是倒叙订阅;
3)发射事件和接收事件
ObservableEmitter发送事件;
4)接收事件顺序
onNext()方法执行顺序:ObservableCreate类中匿名类CreateEmitter类--ObservableSubscribeOn类中匿名类ObserveOnObserver--ObservableObserveOn类匿名内部类ObserveOnObserver--LambdaObserver--onNext.accept(t);
即:调用ObservableCreate类中匿名类CreateEmitter的onNext()方法,中调用ObservableSubscribeOn类中匿名类ObserveOnObserver的onNext()方法;然后调用ObservableObserveOn类匿名内部类ObserveOnObserver的onNext();然后调用LambdaObserver类中的onNext()方法,在LambdaObserver方法中调用onNext.accept(t),接收事件;
从上面的分析:相关的操作符都是通过订阅关系、接收事件的循环实现各种操作符需要的效果;
在ObservableSubscribeOn切换到指定线程发送事件;如何将切换到指定线程接收事件呢?
ObservableObserveOn类subscribeActual()方法
@Override
protected void subscribeActual(Observer<? super T> observer) {
//默认情况下,在那个线程发送事件,就在那个线程接收事件
if (scheduler instanceof TrampolineScheduler) {
source.subscribe(observer);
} else {
//调用的是HandlerScheduler的实现方法createWorker(),创建HandlerWorker实例;
Scheduler.Worker w = scheduler.createWorker();
source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
}
}
HandlerScheduler内部创建Handler;
看下ObservableObserveOn类匿名内部类ObserveOnObserver类中onNext()方法;
@Override
public void onNext(T t) {
if (done){
return;
}
if (sourceMode != QueueDisposable.ASYNC) {
queue.offer(t);
}
schedule();
}
再看下schedule()方法;安排一个Runnable来执行,就是observeOn()指定的线程;
void schedule() {
if (getAndIncrement() == 0) {
worker.schedule(this);
}
}
schedule()方法
@NonNull
public Disposable schedule(@NonNull Runnable run) {
return schedule(run, 0L, TimeUnit.NANOSECONDS);
}
HandlerWorker是HandlerScheduler的内部类,继承了Worker类;看下其内部的schedule()实现方法;把给定的Runnable包装成
ScheduledRunnable,然后发送handler消息
@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);
//把给定的Runnable包装成ScheduledRunnable
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)));//发送Handler消息
if (disposed) {
handler.removeCallbacks(scheduled);
return Disposables.disposed();
}
return scheduled;
}
接收事件切换线程的原理总结:创建指定线程的Worker实例,调用schedule()方法,在具体的Worker实现类中调用schedule()方法,在此方法中把给定的Runnable包装成ScheduledRunnable,发送Handler消息或者线程池调用;
借用一张图来总结来自http://blog.csdn.net/u011291205/article/details/73044256,可以很好的总结上面的分析内容;
以上就是Schedulers原理实现的全部流程,可自行断点跟踪;如有问题,请多指教!
参考文档
http://blog.csdn.net/u011291205/article/details/73044256