Análisis del código fuente de RxJava2.X (2): Explorando el principio del cambio de hilo de suscripción de RxJava2

Prefacio

Basado en RxJava2.1.1,
usamos la explicación detallada de RxJava2.0 en el análisis preliminar previo (1) del flujo de RxJava desde la creación hasta la ejecución. También entiendo que onComplete (); y onError (t) de RxJava; tienen solo un secreto que se ejecutará.
Esta vez exploraremos el principio de implementación del cambio de hilo RxJava2.x. Sea consciente de lo que es y por qué es.
¡Bien, comencemos nuestro viaje de descubrimiento!

De la demostración al código fuente

Echemos un vistazo a la demostración sin cambiar de hilo:

Observable.create(new ObservableOnSubscribe<Integer>() {
    
    

    @Override
    public void subscribe(ObservableEmitter<Integer> e) throws Exception {
    
    
        Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
        e.onNext(123);
  Log.d("MainActivity","onNext(发送) :"+ "123");
    }
})
        .subscribe(new Observer<Integer>() {
    
    
    @Override
    public void onSubscribe(Disposable d) {
    
    

    }

    @Override
    public void onNext(Integer integer) {
    
    
        Log.d("MainActivity","onNext(接收) :"+integer + "");
        Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
    }

    @Override
    public void onError(Throwable e) {
    
    

    }

    @Override
    public void onComplete() {
    
    

    }
});


====================================
结果是:
2021-01-23 16:27:02.667 16788-16788/com.damon.myapplication D/MainActivity: 工作线程是:main
2021-01-23 16:27:02.668 16788-16788/com.damon.myapplication D/MainActivity: onNext(发送) :123
2021-01-23 16:27:02.668 16788-16788/com.damon.myapplication D/MainActivity: 工作线程是:main
2021-01-23 16:27:02.668 16788-16788/com.damon.myapplication D/MainActivity: onNext(接收) :123



Echemos un vistazo a la versión con la función de cambio de hilo:

 Observable.create(new ObservableOnSubscribe<Integer>() {
    
    

            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
    
    
                Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
                Log.d("MainActivity","onNext(发送) :"+ "123");
                e.onNext(123);

            }
        }).subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe(new Observer<Integer>() {
    
    
            @Override
            public void onSubscribe(Disposable d) {
    
    
                Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
                Log.d("MainActivity","onSubscribe :");
            }

            @Override
            public void onNext(Integer integer) {
    
    
                Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
                Log.d("MainActivity","onNext(接收) :"+integer + "");

            }

            @Override
            public void onError(Throwable e) {
    
    

            }

            @Override
            public void onComplete() {
    
    

            }
        });

=======================================
结果是:
2021-01-25 10:59:51.859 3508-3508/com.damon.myapplication D/MainActivity: 工作线程是:main
2021-01-25 10:59:51.859 3508-3508/com.damon.myapplication D/MainActivity: onSubscribe :
2021-01-25 10:59:51.871 3508-3691/com.damon.myapplication D/MainActivity: 工作线程是:RxCachedThreadScheduler-1
2021-01-25 10:59:51.871 3508-3691/com.damon.myapplication D/MainActivity: onNext(发送) :123
2021-01-25 10:59:51.872 3508-3694/com.damon.myapplication D/MainActivity: 工作线程是:RxCachedThreadScheduler-2
2021-01-25 10:59:51.872 3508-3694/com.damon.myapplication D/MainActivity: onNext(接收) :123


Obviamente, el onSubsriber () de Observer se llama en ese hilo y se ejecuta en ese hilo (en este caso, se llama en el hilo principal). Tanto el envío como la recepción de eventos abrirán un hilo de Io para su ejecución.
Bien, después de leer el fenómeno, ¡comencemos a mirar la esencia! Pero, ¿por dónde empiezas? Sigue siendo la forma antigua, comience donde se active el comportamiento ( ̄∇ ̄)
Bien, primero exploremos el método subscribeOn para cambiar los subprocesos de trabajo observables:

Class Observable{
    
    
......
    @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));
    }
    
    }

Vi RxJavaPlugins.onAssembly. Lo analicé antes y entregué el gancho. Ahora se puede considerar que devuelve el Obserable entrante. Aquí este es nuestro observable, y el programador es el Programador que pasamos; continuamos mirando ObservableSubscribeOn:

public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
    
    ....}

Hereda AbstractObservableWithUpstream:

 abstract class AbstractObservableWithUpstream<T, U> extends Observable<U> implements HasUpstreamObservableSource<T> {
    
    

        /** The source consumable Observable. */
      protected final ObservableSource<T> source;

        /**
     * Constructs the ObservableSource with the given consumable. * @param source the consumable Observable
     */  AbstractObservableWithUpstream(ObservableSource<T> source) {
    
    
            this.source = source;
        }

        @Override
      public final ObservableSource<T> source() {
    
    
            return source;
        }

    }

AbstractObservableWithUpstream hereda de Observable, y su función es guardar el Observable upstream a través del campo fuente. Debido a que Observable es la clase de implementación de la interfaz ObservableSource, podemos pensar que Observable y ObservableSource son iguales en este artículo:
es decir, ObservableSubscribeOn es el Observable una vez. La operación de envoltura está
bien, regresemos y veamos el código fuente de ObservableSubscribeOn:

  public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
    
    
      //1、线程调度器
      final Scheduler scheduler;
      public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
    
    
          //2、存储上游的obserble
          super(source);
          this.scheduler = scheduler;
      }

      @Override
    public void subscribeActual(final Observer<? super T> s) {
    
    
        //以下为关键部分
          //3、对我们下游的observer进行一次wrapper
          final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);
          //4、同样,先自己调用自己的onSubscribe
          s.onSubscribe(parent);
          //5、(高能量聚集了)将调度的线程的Disposable赋值给当前的Disposable。scheduler可以看成是某个线程上的调度器。new SubscribeTask(parent)工作在其指定的线程里面。SubscribeTask是一个Runnable,也就是说调度器触发Runnable的run()运行,
          //***是不是恍然大悟,那么run()里面的代码就是运行在scheduler的线程上了。这样也就实现了线程的切换了。
          parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
      }
      static final class SubscribeOnObserver<T> extends AtomicReference implements Observer<T>, Disposable {
    
    ....}
      ...
      }

Continúe mirando la clase interna SubscribeOnObserver de ObservableSubscribeOn:

static final class SubscribeOnObserver<T> extends AtomicReference<Disposable> implements Observer<T>, Disposable {
    
    

        private static final long serialVersionUID = 8094547886072529208L;
        final Observer<? super T> actual;

        final AtomicReference<Disposable> s;

        SubscribeOnObserver(Observer<? super T> actual) {
    
    
            this.actual = actual;
            this.s = new AtomicReference<Disposable>();
        }

        @Override
        public void onSubscribe(Disposable s) {
    
    
            DisposableHelper.setOnce(this.s, s);
        }

        @Override
        public void onNext(T t) {
    
    
            actual.onNext(t);
        }

        @Override
        public void onError(Throwable t) {
    
    
            actual.onError(t);
        }

        @Override
        public void onComplete() {
    
    
            actual.onComplete();
        }

        @Override
        public void dispose() {
    
    
            DisposableHelper.dispose(s);
            DisposableHelper.dispose(this);
        }

        @Override
        public boolean isDisposed() {
    
    
            return DisposableHelper.isDisposed(get());
        }

        void setDisposable(Disposable d) {
    
    
            DisposableHelper.setOnce(this, d);
        }
    }

SubscribeOnObserver implementa el observer, y se pasa un parámetro del tipo observer en el constructor, lo que indica que la función principal de esta clase es envolver al observador descendente. Desde la perspectiva del método de reescritura, esto también se confirma, y ​​todos son llamado El método correspondiente en el observador aguas abajo.
Ok, continuemos mirando la clase SubscribeTask:

  final class SubscribeTask implements Runnable {
    
    
      private final SubscribeOnObserver<T> parent;

      SubscribeTask(SubscribeOnObserver<T> parent) {
    
    
          this.parent = parent;
      }

      @Override
    public void run() {
    
    
          source.subscribe(parent);
      }
  }

El padre es nuestro observador empaquetado, que almacena al observador descendente dentro

La fuente es almacenar nuestro observable ascendente después de pasar ObservableSubscribeOnwrapper

Entonces, source.subscribe (parent) en la ejecución es que el observador de la envoltura se suscribe al observable upstream, activa el subscribeActual del observable upstream y comienza a distribuir los datos.

La imagen específica puede ser la siguiente:

! [Inserte la descripción de la imagen aquí] (https://img-blog.csdnimg.cn/20210125194618566.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG5NDL Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
,
básicamente, el análisis es importante aquí. claro.
1. Cuando se ejecuta subscribeOn, un (envoltorio) obserabler y un (envoltorio) Observador
original observable -> [(Envoltorio) observable || (Envoltorio) Observador] se insertan en Observable y observer. -> (Original) Observador

2. Observable.subscribe trigger -> (Wrapper) Observable.subscribeActual () llamada interna-> parent.setDisposable (Scheduler.scheduleDirect (new SubscribeTask (parent)));, -> Se llama al programador en el hilo especificado (cambio de hilo completo ) -> SubscribeTask.run, ejecutar la llamada interna -> Original Observable.subscribe ((Wrapper) Observer) trigger -> (Original) Observable.subscribeActual () iniciar la distribución de datos
Ok, en este momento se distribuye a (Wrapper) Observer, que debería ser (Wrapper) Observer se distribuyó a (original) Observer.


Ok, con el pavimento para el análisis de SubscribeOnObserver, podemos analizarlo ahora

parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)))

Primero veamos el programador de oraciones.scheduleDirect ()

   @NonNull
   //以毫秒为单位,无延迟调度
    public Disposable scheduleDirect(@NonNull Runnable run) {
    
    
        return scheduleDirect(run, 0L, TimeUnit.NANOSECONDS);
    }

Devuelve un desechable, veamos si este desechable es realmente el hilo de la programación.

@NonNull
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
    
    
  @NonNull
  public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
    
    
      //13、Worker实现了Disposable的一个调度工作者类
      final Worker w = createWorker();
      //14、hook,排除hook干扰,可以理解为decoratedRun==run
      final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
      //15、DisposeTask同样是实现了Disposable的Task
      DisposeTask task = new DisposeTask(decoratedRun, w);
      //16、开始执行
      w.schedule(task, delay, unit);
      //17、确实是返回了管理run的worker
      return task;
  }
}

Ok, ahora el punto final se transfiere a DisposeTask, le damos ejecución a DisposeTask, y luego el trabajador programa la tarea para iniciar la ejecución.

Bien, entonces podemos adivinar que después de que se ejecuta w.schedule (tarea, retraso, unidad), debería ser un método para programar la tarea, y luego la tarea comienza a ejecutar la ejecución Ejecutable

¿Es verdad? Echemos un vistazo a lo que hace el nuevo DisposeTask (decorationRun, w)

  static final class DisposeTask implements Runnable, Disposable {
    
    
      //18、我们外部传入的runnable
      final Runnable decoratedRun;
      //19、调度工作者
      final Worker w;
      //20、当前线程
      Thread runner;
      DisposeTask(Runnable decoratedRun, Worker w) {
    
    
          this.decoratedRun = decoratedRun;
          this.w = w;
      }

      @Override
    public void run() {
    
    
          //21、获取执decoratedRun的线程
          runner = Thread.currentThread();
          try {
    
    
            //22、OK,高能来了。decoratedRun的run被执行
              decoratedRun.run();
          } finally {
    
    
              dispose();
              runner = null;
          }
      }

      @Override
    public void dispose() {
    
    

          if (runner == Thread.currentThread() && w instanceof NewThreadWorker) {
    
    
              ((NewThreadWorker)w).shutdown();
          } else {
    
    
              //在DisposeTask被取消时,告诉Worker取消,因为DisposeTask是Worker进行管理的
              w.dispose();
          }
      }

      @Override
    public boolean isDisposed() {
    
    
          return w.isDisposed();
      }
  }

Conclusión:
Scheduler.scheduleDirect se llama sin demora -> trabajador-> programación del trabajador-> DisposeTask-> DisposeTask.run ejecución-> decoradoRun.run ();

decoradoRun es nuestra Suscripción externa

Supongo que te gusta

Origin blog.csdn.net/qq_39431405/article/details/113055137
Recomendado
Clasificación