上一次阅读了rxjava的基本流程启动的运作
本次将继续深一步阅读
这章类看看关于rxjava的线程切换原理
首先上一个基本代码
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
e.onNext(1);
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
rxjava用于切换线程的关键代码是:subscribeOn与observeOn这两个函数
找到方法后,当然就是进这个方法看看做了哪些动作,首先是subscribeOn的源码:
@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));
}
创建了一个ObservableSubscribeOn,进入ObservableSubscribeOn:
public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
super(source);
this.scheduler = scheduler;
}
@Override
public void subscribeActual(final Observer<? super T> s) {
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);
s.onSubscribe(parent);
parent.setDisposable(scheduler.scheduleDirect(new Runnable() {
@Override
public void run() {
source.subscribe(parent);
}
}));
}
从上一次章rxjava的流程阅读知道,observable的subscribe是整个流程的启动方法,而subscribe内部调用的正是subscribeActual方法
通过subscribeActual可以看到启动了Scheduler的scheduleDirect,并传入一个runnable,看到runnable大概能猜出来,里面应该就是线程启动的地方了,继续深入scheduleDirect:
public Disposable scheduleDirect(Runnable run, long delay, TimeUnit unit) {
final Worker w = createWorker();
final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
w.schedule(new Runnable() {
@Override
public void run() {
try {
decoratedRun.run();
} finally {
w.dispose();
}
}
}, delay, unit);
return w;
}
创建了一个Worker,并调用Worker的schedule,这个schedule有什么作用呢
我们先看一下Worker
public abstract static class Worker implements Disposable
它只是一个抽象类,所以我们先找到实现类例子,就以io线程的Scheduler为例,首先找到它,我们知道Schedulers这个类维护了许多个线程的单一实例,如IO线程用于网络请求,COMPUTATION线程用于计算。
所以就在Schedulers里面找:
static final Scheduler IO;
果然找到了,继续往下找它的实例化:
static {
SINGLE = RxJavaPlugins.initSingleScheduler(new Callable<Scheduler>() {
@Override
public Scheduler call() throws Exception {
return SingleHolder.DEFAULT;
}
});
COMPUTATION = RxJavaPlugins.initComputationScheduler(new Callable<Scheduler>() {
@Override
public Scheduler call() throws Exception {
return ComputationHolder.DEFAULT;
}
});
IO = RxJavaPlugins.initIoScheduler(new Callable<Scheduler>() {
@Override
public Scheduler call() throws Exception {
return IoHolder.DEFAULT;
}
});
TRAMPOLINE = TrampolineScheduler.instance();
NEW_THREAD = RxJavaPlugins.initNewThreadScheduler(new Callable<Scheduler>() {
@Override
public Scheduler call() throws Exception {
return NewThreadHolder.DEFAULT;
}
});
}
发现所有的线程都在static里面实例。我们只看io的:
IO = RxJavaPlugins.initIoScheduler(new Callable<Scheduler>() {
@Override
public Scheduler call() throws Exception {
return IoHolder.DEFAULT;
}
});
进入initIoScheduler你会发现,这个方法就只是单纯的一些null值判定,然后回调Callable.call,这里可以看到回调里面只有一行代码IoHolder.DEFAULT
这个是什么东西呢,我们在Schedulers里面找到它,是一个内部类:
static final class IoHolder {
static final Scheduler DEFAULT = new IoScheduler();
}
终于看到IoScheduler,话不多说,看一下IoScheduler是什么
public final class IoScheduler extends Scheduler
不出意外,继承了Scheduler ,所以我们回到最初的那个目的,找到它的Worder实现类:
static final class EventLoopWorker extends Scheduler.Worker
一个叫EventLoopWorker的家伙,里面维护了三个对象:CompositeDisposable、CachedWorkerPool、ThreadWorker,还有它的schedule方法,先看schedule方法:
@Override
public Disposable schedule(Runnable action, long delayTime, TimeUnit unit) {
if (tasks.isDisposed()) {
// don't schedule, we are unsubscribed
return EmptyDisposable.INSTANCE;
}
return threadWorker.scheduleActual(action, delayTime, unit, tasks);
}
调用了ThreadWorker.scheduleActual,看一下ThreadWorker是什么:
static final class ThreadWorker extends NewThreadWorker
继承的NewThreadWorder,继续看NewThreadWorder的scheduleActual
public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, TimeUnit unit, DisposableContainer parent) {
Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);
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) {
parent.remove(sr);
RxJavaPlugins.onError(ex);
}
return sr;
}
发现里面有个executor对象,它是什么呢,我们来看看:
private final ScheduledExecutorService executor;
public interface ScheduledExecutorService extends ExecutorService
public interface ExecutorService extends Executor
所以,Worker的schedule启动的正是Executor的schedule或submit
至此rxjava使用subscribeOn线程切换原理大致已经清楚,observeOn也是同理。
补充一点,关于主线程的切换原理,rxjava新增了一个rxandroid依赖,里面新维护了一个AndroidSchedulers类,我们是通过它来切换至主线程的。
那么来看看它的原理
public final class AndroidSchedulers {
private static final class MainHolder {
static final Scheduler DEFAULT = new HandlerScheduler(new Handler(Looper.getMainLooper()));
}
private static final Scheduler MAIN_THREAD = RxAndroidPlugins.initMainThreadScheduler(
new Callable<Scheduler>() {
@Override public Scheduler call() throws Exception {
return MainHolder.DEFAULT;
}
});
/** A {@link Scheduler} which executes actions on the Android main thread. */
public static Scheduler mainThread() {
return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);
}
/** A {@link Scheduler} which executes actions on {@code looper}. */
public static Scheduler from(Looper looper) {
if (looper == null) throw new NullPointerException("looper == null");
return new HandlerScheduler(new Handler(looper));
}
private AndroidSchedulers() {
throw new AssertionError("No instances.");
}
}
切换很简单
static final Scheduler DEFAULT = new HandlerScheduler(new Handler(Looper.getMainLooper()));
就是使用了Looper.getMainLooper()。