很多开发者喜欢使用Rxjava的原因之一应该就是 – 自由的控制线程,而且控制的方式超级简单,利用 subscribeOn() 结合 observeOn()便可切换你想要的线程,超帅的有木有!!
调度器
所谓调度器,其实实质就是线程,想要程序执行的地方。Rxjava提供了一下几种调度器:
// 在当前线程立即开始执行任务
Schedulers.immediate( )
// 用于IO密集型任务,如异步阻塞IO操作,这个调度器的线程池会根据需要增长
// 对于普通的计算任务,请使用Schedulers.computation()
// Schedulers.io( )默认是一个CachedThreadScheduler,很像一个有线程缓存的新线程调度器
Schedulers.io( )
// 用于计算任务,如事件循环或和回调处理,不要用于IO操作(IO操作请使用Schedulers.io())
// 默认线程数等于处理器的数量
Schedulers.computation( )
// 为每个任务创建一个新线程
Schedulers.newThread( )
// 当其它排队的任务完成后,在当前线程排队开始执行
Schedulers.trampoline( )
// 使用指定的Executor作为调度器
Schedulers.from(executor)
subscribeOn和observeOn区别
subscribeOn和observeOn都可以切换线程,区别有2点:
(1)subscribeOn指定数据源执行的线程(也就是一开始创建的Observable被观察者里面的OnSubscribe的call方法要在那个线程执行);observeOn指定下一个开始观察者OnNext方法执行的线程。
(2)subscribeOn无论调用多少次,以最后一次指定的线程为准;observeOn每次调用后,都会影响下一个观察者执行的线程。
关于更多Rxjava线程控制,请参考 给 Android 开发者的 RxJava 详解 的“线程控制:Scheduler (二)”一节。
原理
因为Rxjava控制线程的代码较多,所以我还是以 Rxjava - 简单实现 基础加上线程控制的代码,这样解析起来更容易理解Rxjava的线程调度原理。
在Producer生产者类添加2个方法:
// Producer类
// 相当于Rxjava的subscribeOn方法
public Producer<T> produceOn(Scheduler scheduler) {
return new Producer<>(new ProduceOnDataFactory<>(dataFactory, scheduler));
}
// 相当于Rxjava的observeOn方法
public Producer<T> consumeOn(Scheduler scheduler) {
return new Producer<>(new ConsumeOnDataFactory<>(this, scheduler));
}
我们还是以例子来分析:
Log.e(getClass().getName(), "origin thread name ---> " + Thread.currentThread().getName());
Producer.create(new DataFactory<String>() {
@Override
public void create(Consumer<String> consumer) {
Log.e(getClass().getName(), "create thread name ---> " + Thread.currentThread().getName());
consumer.onNext("Hello");
consumer.onNext("World");
consumer.onCompleted();
}
}).produceOn(Schedulers.getWorkScheduler()).consumeOn(Schedulers.getMainScheduler()).add(new Consumer<String>() {
@Override
public void onCompleted() {
Log.e(getClass().getName(), "completed is called");
}
@Override
public void onNext(String result) {
Log.e(getClass().getName(), "onNext thread name ---> " + Thread.currentThread().getName());
Log.e(getClass().getName(), "course name : " + result);
}
@Override
public void onError(Exception exception) {
Log.e(getClass().getName(), "error is called");
}
});
打印结果:
origin thread name ---> main
create thread name ---> pool-1-thread-1
onNext thread name ---> main
course name : Hello
onNext thread name ---> main
course name : World
completed is called
从结果看,线程发生了切换,我们来分析代码,初始的Producer调用了produceOn方法:
// Producer类
// 相当于Rxjava的subscribeOn方法
public Producer<T> produceOn(Scheduler scheduler) {
return new Producer<>(new ProduceOnDataFactory<>(dataFactory, scheduler));
}
创建了ProduceOnDataFactory数据工厂,返回新的Producer生产者,新的Producer生产者又调用了consumeOn方法:
// Producer类
// 相当于Rxjava的observeOn方法
public Producer<T> consumeOn(Scheduler scheduler) {
return new Producer<>(new ConsumeOnDataFactory<>(this, scheduler));
}
创建了ConsumeOnDataFactory数据工厂,返回新的Producer生产者,然后调用add消费者,此时ConsumeOnDataFactory的create方法先调用:
// ConsumeOnDataFactory类
// 此时的source是produceOn之后创建的Producer生产者
private Producer<T> source;
// 调度器,Schedulers.getMainScheduler()
private Scheduler scheduler;
@Override
// consumer为例子中最后add的消费者
public void create(Consumer<T> consumer) {
// 代理consumer,待会再解析
ScheduleConsumer scheduleConsumer = new ScheduleConsumer(consumer, scheduler);
source.add(scheduleConsumer);
}
create方法中,最终调用了source的add方法,那么produceOn之后创建的Producer生产者的数据工厂ProduceOnDataFactory的create方法就会执行:
// ProduceOnDataFactory类
// source为初始创建的数据工厂,也就是例子中 Producer.create(这个工厂)
private DataFactory<T> source;
// 调度器,Schedulers.getWorkScheduler()
private Scheduler scheduler;
@Override
// consumer为ScheduleConsumer
public void create(final Consumer<T> consumer) {
scheduler.schedule(new Runnable() {
@Override
public void run() {
source.create(consumer);
}
});
}
这里可以说一下调度器,我简单实现了一下:
// 调度器接口
public interface Scheduler {
void schedule(Runnable command);
}
// 主线程调度器
public class MainScheduler implements Scheduler {
private static Handler handler;
@Override
public void schedule(Runnable command) {
getWorker().post(command);
}
private static Handler getWorker() {
synchronized (MainScheduler.class) {
if (handler == null) {
handler = new Handler(Looper.getMainLooper());
}
return handler;
}
}
}
// 工作(异步)线程调度器
public class WorkScheduler implements Scheduler {
private static ExecutorService executorService;
@Override
public void schedule(Runnable command) {
getWorker().execute(command);
}
private ExecutorService getWorker() {
synchronized (WorkScheduler.class) {
if (executorService == null) {
executorService = Executors.newCachedThreadPool();
}
return executorService;
}
}
}
// 总调度器
public class Schedulers {
private static class MainSchedulerHolder {
private static final MainScheduler INSTANCE = new MainScheduler();
}
private static class WorkSchedulerHolder {
private static final WorkScheduler INSTANCE = new WorkScheduler();
}
public static Scheduler getMainScheduler() {
return MainSchedulerHolder.INSTANCE;
}
public static Scheduler getWorkScheduler() {
return WorkSchedulerHolder.INSTANCE;
}
}
关于调度器很容易看得明白的,不再详解。我们继续回到ProduceOnDataFactory的create方法:
// ProduceOnDataFactory类
// source为初始创建的数据工厂,也就是例子中 Producer.create(这个工厂)
private DataFactory<T> source;
// 调度器Schedulers.getWorkScheduler(),工作线程调度器
private Scheduler scheduler;
@Override
// consumer为ScheduleConsumer
public void create(final Consumer<T> consumer) {
scheduler.schedule(new Runnable() {
@Override
public void run() {
source.create(consumer);
}
});
}
调用WorkScheduler的schedule方法,便把source的create扔进线程池执行了,这就达到切换线程的效果了。我们继续,当source的create方法执行consumer.onNext(“Hello”)时,ScheduleConsumer的onNext方法就会执行:
// ScheduleConsumer类
// consumer为例子中最后add的消费者
private Consumer<T> source;
// 调度器,Schedulers.getMainScheduler()
private Scheduler scheduler;
@Override
public void onNext(final T result) {
// 调用主线程执行source的onNext方法
scheduler.schedule(new Runnable() {
@Override
public void run() {
source.onNext(result);
}
});
}
这样,例子中最后add的消费者的onNext方法放到主线程执行了。是不是很清晰?!
还不是很清晰,还是建议看 给 Android 开发者的 RxJava 详解 的“线程控制:Scheduler (二)”一节。
代码已经更新到我的github库,地址:https://github.com/JohanMan/simplerxjava,欢迎下载研究!!
参考资料
给 Android 开发者的 RxJava 详解
RxJava多线程操作