【译】在正确的线程上观察

作者: 小鄧子 | 来源:发表于2015-10-06 06:09 被阅读3612次

尽管很多人了解RxJava的基本逻辑,但是在Observable链和操作符究竟运行在哪个线程,仍然会有许多困惑。

首先,让我们梳理清晰,在RxJava中.subsribeOn( ).observeOn( )区别:

  1. .subsribeOn( )操作符可以改变Observable应该在哪个调度器上执行任务。

  2. .observeOn( )操作符可以改变Observable将在哪个调度器上发送通知。

  3. 另外,你需要知道,默认情况下,链上的操作符将会在调用.subsribeOn( )的那个线程上执行任务。

一些例子##

1. 主线程或者 .subscribe( )所在线程

如果在Android的ActivityonCreate( )方法中,也就是主线程中使用如下代码:

Observable.just(1,2,3)
  .subscribe( );

表现会像这样:

2. 调用 .subscribeOn( )

尽管代码片段在主线程中,但是整个代码块将运行在.subscribeOn( )定义的线程上:

Observable.just(1,2,3)
  .subscribeOn(Schedulers.newThread())
  .subscribe();

表现会像这样:

3. 调用 .observeOn( )

如果你的代码片段在主线程中,默认情况下Observable的创建是在.subscribeOn( )定义的线程上,但是,调用.observeOn( )之后,余下的代码将会执行在.observeOn( )所定义的线程上:

Observable.just(1,2,3)
  .observeOn(Schedulers.newThread())
  .subscribe();

3. 合并逻辑

照理合并操作符,放在一起就像这样:

Observable.just(1,2,3)
  .subscribeOn(Schedulers.newThread())
  .observeOn(Schedulers.newThread())
  .subscribe();

一些技巧##

1. UI线程运行异常

Observable.just(1,2,3)
  .subscribeOn(Schedulers.newThread())
  .subscribe(/** 与UI线程相关的逻辑 **//);

很明显,这是错误哒。

2. 保证逻辑运行在工作线程中

如果存在以下代码片段:

 Observable.just(1,2,3)
  .subscribeOn(Schedulers.newThread())
  .observeOn(AndroidSchedulers.mainThread())
  
  .flatMap(/** 与UI线程无关的逻辑**//)
  
  .subscribe();

请用以下代码替代:

Observable.just(1,2,3)
  .subscribeOn(Schedulers.newThread())

  .flatMap(/** 与UI线程无关的逻辑**//)

  .observeOn(AndroidSchedulers.mainThread())
  .subscribe();

通过用第二段代码代替第一段,.flatMap( )操作符(或者在这一点的其他逻辑操作符)将运行在后台线程。这样做就不会阻塞UI线程,同时可以防患ANR或其他类似问题的发生。看起来有点像AsyncTask模式,尽可能的把逻辑放在的.doInBackground( )中,而不是.onPostExecute( )

3. 取决于更早的 .subscribeOn( )

以下代码:

Observable.just(1,2,3)
  .subscribeOn(thread1)
  .subscribeOn(thread2)
  .subscribe();

因为thread1的逻辑将会覆盖thread2,所以Observable的创建和.subscribe( )的逻辑处理都将运行在thread1中。因此,根本没有必要写多个.subscribeOn( )操作符。

相关文章

  • 【译】在正确的线程上观察

    原文链接:Observe on the correct thread原文作者: Dionysis Lorentzo...

  • 在正确的线程上使用Observable【译】

    GitHub 博客:在正确的线程上使用Observable【译】

  • Java 线程安全与锁的那些事

    线程安全 何为线程安全?维基百科上是这样描述的:线程安全是指函数、函数库在多线程环境中被调用时,能够正确地处理多个...

  • rxjava笔记

    导包 被观察者 观察者 观察者简写 切换线程 在onNext之前执行 是属于Observar的线程 map操作符...

  • 线程安全

    线程安全:指某个函数、函数库在多线程环境中被调用时,能够正确地处理多个线程之间的共享变量,使程序功能正确完成。 在...

  • java设计模式--观察者模式

    观察者模式 观察者--OOD线程 简单理解 起一个被观察者线程和一个观察者线程。观察者不断的循环检查被观察者状态是...

  • AsyncTask指南

    AsyncTask指南 通过AsyncTask,可以正确,轻松地使用UI线程。此类允许您执行后台操作并在UI线程上...

  • RxJava 并行操作

    上一篇文章RxJava 线程模型分析详细介绍了RxJava的线程模型,被观察者(Observable、Flowab...

  • 4-1 启动线程的方式

    启动线程的正确方式:start()一、start()有哪些作用?1,启动新线程线程对象在初始化之后被Main线程调...

  • RxJava使用案例(1):线程调度

    这一章主要介绍RxJava的线程调度和切换,由于被观察者和观察者都是在主线程中创建,那么他们的工作流程就会在主线程...

网友评论

  • noter: Observable.just("1").subscribeOn(Schedulers.newThread()).map(s -> {
    System.out.println("subscribeOn(Schedulers.newThread() " + Thread.currentThread().getName());
    return s;
    }).subscribeOn(Schedulers.io()).map(s -> {
    System.out.println("subscribeOn(Schedulers.io() " + Thread.currentThread().getName());
    return s;
    }).observeOn(Schedulers.io()).map(s -> {
    System.out.println("observeOn(Schedulers.io() " + Thread.currentThread().getName());
    return s;
    }).observeOn(Schedulers.computation()).map(s -> {
    System.out.println("observeOn(Schedulers.computation() " + Thread.currentThread().getName());
    return s;
    }).subscribeOn(Schedulers.immediate()).map(s -> {
    System.out.println("subscribeOn(Schedulers.immediate() " + Thread.currentThread().getName());
    return s;
    })
    .subscribe((a) -> {
    System.out.println("onComplete " + Thread.currentThread().getName());
    });
    验证了下,结果一致, :smile:
    subscribeOn(Schedulers.newThread() RxNewThreadScheduler-1
    subscribeOn(Schedulers.io() RxNewThreadScheduler-1
    observeOn(Schedulers.io() RxCachedThreadScheduler-1
    observeOn(Schedulers.computation() RxComputationThreadPool-3
    subscribeOn(Schedulers.immediate() RxComputationThreadPool-3
    onComplete RxComputationThreadPool-3
    妙法莲花1234:@小鄧子 同酔,看着好蛋疼
    小鄧子:@noter 评论区的代码居然不支持markdown,也是醉了。 :pensive:
  • 风中树木呢喃:天啊!能稍微解释一下吗?我对不懂的东西完全好奇!特别是完全不懂的东西!虽不懂,但我知道你很专业!
  • 91b293462d1c:> 因此,根本没有必要写多个.subscribeOn( )操作符。

    有些case是需要用到多个.subscribeOn( )的,比如

    // 当前线程不是UI线程
    Observable.create(...) // 这是一个IO操作
    .subscribeOn(Schedulers.io())
    .doOnSubscribe(() -> view.XXX) // 这是一个UI操作,例如显示进度条
    .subscribeOn(AndroidSchedulers.mainThread())
    ...
    小鄧子:@流火枫林 因为Observable.create( )会生成一个“冷”的Observable,而且do操作符,尤其是doOnSubscribe( )比较特殊,采用倒序的方式,离订阅者越近的,越早执行,如果离订阅者最近的doOnSubscribe( )的下线并没有subscribeOn( ),则其线程取决于调用该操作符的线程。关于响应式编程,应该尽量保证Don't break the chain,所以subscribeOn( )和observeOn( )还是使用compose( )操作符吧。

本文标题:【译】在正确的线程上观察

本文链接:https://www.haomeiwen.com/subject/wsngcttx.html