RxJava2.0- Schedulers线程切换原理分析

简介

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

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RxJava 切换线程内存泄漏的原因可能有以下几点: 1. 订阅关系未正确取消:在使用RxJava进行线程切换时,如果没有正确取消订阅关系,就可能导致内存泄漏。因为订阅关系会持有被观察者和观察者之间的引用,如果未及时取消订阅,就会导致观察者无法被释放,从而造成内存泄漏。 2. 使用错误的调度器:在RxJava中,切换线程需要使用Scheduler来指定要切换到的线程。如果使用了错误的调度器,可能导致线程资源无法正确释放,从而造成内存泄漏。 3. 长时间运行的任务:如果在使用RxJava进行线程切换时,执行的任务是一个长时间运行的任务,可能会导致内存泄漏。因为长时间运行的任务可能会持有一些资源,如果没有及时释放这些资源,就会造成内存泄漏。 为避免RxJava切换线程内存泄漏,可以采取以下几个措施: 1. 及时取消订阅关系:在不需要继续观察的时候,及时取消订阅关系,可以使用CompositeDisposable来管理多个订阅关系,确保在不需要时能够正确取消订阅。 2. 使用正确的调度器:在进行线程切换时,确保使用正确的调度器,比如使用Schedulers.io()进行IO操作,使用AndroidSchedulers.mainThread()进行主线程操作。 3. 避免长时间运行的任务:如果任务可能会持续较长时间,可以考虑使用takeUntil等操作符来限制任务的执行时间。 通过以上措施,可以有效避免RxJava切换线程内存泄漏的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值