默认情况下rxjava中生产者和订阅者都是在当前线程中执行。Scheduler就是用来切换生产者和订阅者执行的线程。
Scheduler默认内置了一些内置的Scheduler,方便针对不同的任务选择.
subscribeOn指定subscribe()所发生的线程,或者叫做事件产生的线程
observeOn 指定 Subscriber 所运行在的线程,或者叫做事件消费的线程
上面了解了rxjava线程调度的基本知识。这里抛出一个问题:一般一个生产者会经过多个操作符的处理,最后流到订阅者由订阅者处理。如果在多个操作符执行过程中多次调用subscribeOn和ObserveOn,那怎么判断这些操作运行的线程呢?
我写了一个小demo,如下:
Observable
.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber super Integer> subscriber) {
//main
Log.d("thread10", "map method in thread: " + Thread.currentThread().getName());
subscriber.onNext(1);
}
})
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(Schedulers.io())
.map(new Func1<Integer, Integer>() {
@Override
public Integer call(Integer integer) {
//io
Log.d("thread11", "map method in thread: " + Thread.currentThread().getName());
return integer;
}
})
.observeOn(AndroidSchedulers.mainThread())
.map(new Func1<Integer, Integer>() {
@Override
public Integer call(Integer integer) {
//main
Log.d("thread12", "map method in thread: " + Thread.currentThread().getName());
return integer;
}
})
.observeOn(Schedulers.io())
.map(new Func1<Integer, Integer>() {
@Override
public Integer call(Integer integer) {
//io
Log.d("thread13", "map method in thread: " + Thread.currentThread().getName());
return integer;
}
})
.observeOn(AndroidSchedulers.mainThread())
.map(new Func1<Integer, Integer>() {
@Override
public Integer call(Integer integer) {
//main
Log.d("thread14", "map method in thread: " + Thread.currentThread().getName());
return integer;
}
})
.observeOn(Schedulers.io())
.subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Integer integer) {
//io
Log.d("thread15", "map method in thread: " + Thread.currentThread().getName());
System.out.print(integer + '\n');
}
});
02-09 14:13:50.245 12755-12755/com.sankuai.moviepro D/thread10: map method in thread: main
02-09 14:13:50.246 12755-13004/com.sankuai.moviepro D/thread11: map method in thread: RxIoScheduler-5
02-09 14:13:50.246 12755-12755/com.sankuai.moviepro D/thread12: map method in thread: main
02-09 14:13:50.246 12755-13007/com.sankuai.moviepro D/thread13: map method in thread: RxIoScheduler-8
02-09 14:13:50.246 12755-12755/com.sankuai.moviepro D/thread14: map method in thread: main
02-09 14:13:50.246 12755-13006/com.sankuai.moviepro D/thread15: map method in thread: RxIoScheduler-7
上面打印出了具体的输出。这里不从源码角度分析线程调度,直接给结论,大家可以先记住。后面会简要分析rxjava的源码,到时候会具体分析线程调度这块内容。
结论:
subscribeOn(Schedulers.io())影响的是他前面执行所在的线程,而observeOn(AndroidSchedulers.mainThread())影响的是他后面执行所在的线程。
subscribeOn()它指示Observable在一个指定的调度器上创建(只作用于被观察者创建阶段)。只能指定一次,如果指定多次则以第一次为准
observeOn()指定在事件传递(加工变换)和最终被处理(观察者)的发生在哪一个调度器。可指定多次,每次指定完都在下一步生效。
//new Observable.just()执行在新线程
Observable.create(new Observable.just(getFilePath())
//指定在新线程中创建被观察者
.subscribeOn(Schedulers.newThread())
//将接下来执行的线程环境指定为io线程
.observeOn(Schedulers.io())
//map就处在io线程
.map(mMapOperater)
//将后面执行的线程环境切换为主线程,
//但是这一句依然执行在io线程
.observeOn(AndroidSchedulers.mainThread())
//指定线程无效,但这句代码本身执行在主线程
.subscribeOn(Schedulers.io())
//执行在主线程
.subscribe(mSubscriber);
Observable.just(1, 2, 3).concatWith(Observable.error(new Error()))
.subscribeOn(Schedulers.newThread())
.doOnError(new Action1() {
@Override
public void call(Throwable throwable) {
Log.d("eror", "doonerror");
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1() {
@Override
public void call(Integer integer) {
}
}, new Action1() {
@Override
public void call(Throwable throwable) {
Log.d("eror", "onerr");
}
});
如果不涉及多线程,onError和doOnError无区别。但是这里涉及多线程。
doOnError是在子线程中执行,eror在主线程中执行。
理解RxJava的线程模型
http://www.importnew.com/23325.html
简单谈谈RxJava和多线程并发
http://www.jb51.net/article/107313.htm
RxJava中多线程机制
http://blog.csdn.net/yaoyasong/article/details/50666743
RxJava - 小心 observeOn 的陷阱
https://www.jianshu.com/p/238b286ac69c
【译】在正确的线程上观察
https://www.jianshu.com/p/72911b9ba2d7
RxJava中的doOnSubscribe默认执行线程分析
http://blog.csdn.net/jdsjlzx/article/details/59223182