rxjava2 - 在线程池上执行任务的简单示例,在单个线程上进行订阅

时间:2017-09-03 21:27:02

标签: java kotlin rx-java2

我正在尝试以下任务来了解RxJava:

  • 给出一个URL列表
  • 对线程池上的每个URL执行HTTP请求
  • 对于每个结果,将一些数据插入到SQLite数据库中(此处不进行多线程处理)
  • 阻止方法直至完成

所以我在Kotlin试了一下:

val ex = Executors.newFixedThreadPool(10)
Observable.fromIterable((1..100).toList())
    .observeOn(Schedulers.from(ex))
    .map { Thread.currentThread().name }
    .subscribe { println(it + " " + Thread.currentThread().name }

我希望它能打印

pool-1-thread-1 main
pool-1-thread-2 main
pool-1-thread-3 main
pool-1-thread-4 main
....

然而它打印:

pool-1-thread-1 pool-1-thread-1
pool-1-thread-1 pool-1-thread-1
pool-1-thread-1 pool-1-thread-1

任何人都可以纠正我对这是如何工作的误解吗?为什么它不使用线程池的所有线程?如何让我的订阅者在主线程或块上运行直到完成?

2 个答案:

答案 0 :(得分:4)

Rx并不是一个并行执行服务,使用Java的流api。 Rx事件是同步的,并且随后将流过流。在构建流时,observeOn将请求一次线程并在该线程上逐个处理排放。

您还希望在主线程上执行subscribeobserveOn切换线程,并在该线程上发生所有下游事件。如果要切换到主线程,则必须在observeOn之前插入另一个subscribe

答案 1 :(得分:1)

要使map块中的代码并行工作,您应该使用自己的调度程序将其包装到observable中:

val ex = Executors.newFixedThreadPool(10)
    val scheduler = Schedulers.from(ex)
    Observable.fromIterable((1..100).toList())
            .flatMap {
                Observable
                        .fromCallable { Thread.currentThread().name }
                        .subscribeOn(scheduler)
            }
            .subscribe { println(it + " " + Thread.currentThread().name) }

在这种情况下,您将看到结果:

pool-1-thread-1 pool-1-thread-1
pool-1-thread-2 pool-1-thread-1
pool-1-thread-3 pool-1-thread-1
pool-1-thread-4 pool-1-thread-1
...

您可以查看解释此行为的文章RxJava - Achieving Parallelization

此外,RxJava 2.0.5引入了ParallelFlowable API