默认情况下,不做任何线程处理,Observable和Observer处于同一线程中。如果想要切换线程,则可以使用subscribeOn()和observeOn()。
1.subscribeOn
subscribeOn通过接受一个Scheduler参数,来指定对数据的处理运行在特定的线程调度器Scheduler上。
若多次执行subscribeOn,则只有一次起作用。
单击subscribeOn()的源码可以看到,每次调用subscribeOn()都会创建一个ObservableSubscribeOn对象。
/**
* Asynchronously subscribes Observers to this ObservableSource on the specified {@link Scheduler}.
*
* @param scheduler
* the {@link Scheduler} to perform subscription actions on
* @return the source ObservableSource modified so that its subscriptions happen on the
* specified {@link Scheduler}
* @see #observeOn
*/
@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真正发生订阅的方法是subscribeActual(Observer<? super T> observer)。
@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);
}
}));
}
其是,SubscribeOnObserver是下游Observer的OnSubscribe(Disposable disposable)方法
s.onSubscribe(parent);
然后,将子线程的操作加入Disposable管理中,加入Disposable后可以方便上下游的统一管理。在这里,已经调用了对应Scheduler的scheduleDirect()方法。scheduleDirect()传入的是一个Runnable。
parent.setDisposable(scheduler.scheduleDirect(new Runnable() {
@Override
public void run() {
source.subscribe(parent);
}
}));
此时,已经再对应的Scheduler线程中运行了:
source.subscribe(parent);
在RxJava的链式操作中,数据的处理是自下而上的,这点与数据发射正好相反。如果多次调用subscribeOn,则最上面的线程切换最晚执行,所以就变成了只有第一次切换线程才有效。
2.observeOn
observeOn同样接受一个Scheduler参数,用来指定下游操作运行在特定的线程调度器Scheduler上。
若多次执行observeOn,则每次都起作用,线程会一直切换。
单击observeOn的源码可以看到,每次调用observeOn()都会创建一个ObservableObserveOn对象。
/**
* Modifies an ObservableSource to perform its emissions and notifications on a specified {@link Scheduler},
* asynchronously with an unbounded buffer with {@link Flowable#bufferSize()} "island size".
*
* <p>Note that onError notifications will cut ahead of onNext notifications on the emission thread if Scheduler is truly
* asynchronous. If strict event ordering is required, consider using the {@link #observeOn(Scheduler, boolean)} overload.
*
* @param scheduler
* the {@link Scheduler} to notify {@link Observer}s on
* @return the source ObservableSource modified so that its {@link Observer}s are notified on the specified
* {@link Scheduler}
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> observeOn(Scheduler scheduler) {
return observeOn(scheduler, false, bufferSize());
}
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
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));
}
ObservableObserveOn真正发生订阅的方法是subscribeActual(Observer<? super T> observer)。
@Override
protected void subscribeActual(Observer<? super T> observer) {
//如果scheduler是TrampolineScheduler,则上游事件和下游事件会立即产生订阅。
if (scheduler instanceof TrampolineScheduler) {
source.subscribe(observer);
} else {
//否则scheduler会创建自己的Worker,然后上游事件和下游事件产生订阅,生成一个ObserveOnObserver对象,封装了下游真正的Observer。
Scheduler.Worker w = scheduler.createWorker();
source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
}
}
如果scheduler是TrampolineScheduler,则上游事件和下游事件会立即产生订阅。
如果不是TrampolineScheduler,则scheduler会创建自己的Worker,然后上游事件和下游事件产生订阅,生成一个ObserveOnObserver对象,封装了下游真正的Observer。
ObserveOnObserver是ObservableObserveOn的内部类,实现了Observer、Runnable接口。与SubscribeOnObserver不同的是,SubscribeOnObserver实现了Observer、Disposable接口。
在ObserveOnObserver的onNext()中,schedule()执行了具体调度的方法。
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != QueueDisposable.ASYNC) {
queue.offer(t);
}
schedule();
}
void schedule() {
if (getAndIncrement() == 0) {
// 该成员变量worker: final Scheduler.Worker worker;
// this指的是当前的ObserveOnObserver对象,this实现了 Runnable接口
worker.schedule(this);
}
}
然后,再来看看Runnable接口的实现方法run(),这个方法是在Worker对应的线程里执行的。drainNormal()会取出ObserveOnObserver的queue里的数据进行发送。
@Override
public void run() {
if (outputFused) {
drainFused();
} else {
drainNormal();
}
}
若下游多次调用observeOn(),则线程会一直切换。每次切换线程,都会把对应的Observe对象的各个方法的处理执行在指定的线程中。
注意:这是与subscribeOn()方法的不同之处,多次subscribeOn(),只有一次起作用。
简单示例:
public void multipleUsingSubscribeOnAndObserveOnTest() {
Observable.just("HELLO WORLD")
.subscribeOn(Schedulers.single())
.map(new Function<String, String>() {
@Override
public String apply(@NonNull String s) throws Exception {
s = s.toLowerCase();
print("map1:");
System.out.println(s);
return s;
}
})
.observeOn(Schedulers.io())
.map(new Function<String, String>() {
@Override
public String apply(@NonNull String s) throws Exception {
s = s + " tony.";
print("map2");
System.out.println(s);
return s;
}
})
.subscribeOn(Schedulers.computation())
.map(new Function<String, String>() {
@Override
public String apply(@NonNull String s) throws Exception {
s = s + " it is a test.";
print("map3");
System.out.println(s);
return s;
}
})
.observeOn(Schedulers.newThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
print("subscribe");
System.out.println(s);
}
});
}
public void print(String label) {
System.out.println(label);
System.out.println(Thread.currentThread().getName());
}
输出结果:
2020-06-23 14:51:31.699 2627-2646/? I/System.out: map1:
2020-06-23 14:51:31.699 2627-2646/? I/System.out: RxSingleScheduler-1
2020-06-23 14:51:31.699 2627-2646/? I/System.out: hello world
2020-06-23 14:51:31.701 2627-2647/? I/System.out: map2
2020-06-23 14:51:31.701 2627-2647/? I/System.out: RxCachedThreadScheduler-1
2020-06-23 14:51:31.701 2627-2647/? I/System.out: hello world tony.
2020-06-23 14:51:31.702 2627-2647/? I/System.out: map3
2020-06-23 14:51:31.702 2627-2647/? I/System.out: RxCachedThreadScheduler-1
2020-06-23 14:51:31.702 2627-2647/? I/System.out: hello world tony. it is a test.
2020-06-23 14:51:31.703 2627-2648/? I/System.out: subscribe
2020-06-23 14:51:31.703 2627-2648/? I/System.out: RxNewThreadScheduler-1
2020-06-23 14:51:31.703 2627-2648/? I/System.out: hello world tony. it is a test.
说明: 在多次使用subscribeOn和observeOn时,如同上述例子, 具体的调用线程说明:
- subscribeOn(): Schedulers.single()
- observeOn():Schedulers.io()
- subscribeOn():Schedulers.io()
注意:此处调用的线程 不是
Schedulers.single(),因为已经调用过一次subscribeOn(),因而再次调用该方法时会使用其上一次的线程,即 observeOn()所调用的线程 ,但不是上一次subscribeOn()的线程!!!
- observeOn():Schedulers.newThread()