我在普通的JDK 8上。我有这个简单的RxJava示例:
Observable
.from(Arrays.asList("one", "two", "three"))
.doOnNext(word -> System.out.printf("%s uses thread %s%n", word, Thread.currentThread().getName()))
//.subscribeOn(Schedulers.newThread())
.subscribe(word -> System.out.println(word));
并且它逐行打印出单词,与线程的信息交织在一起,这是主要的'对于所有下一个电话,正如预期的那样。
但是,当我取消注释subscribeOn(Schedulers.newThread())
电话时,根本不会打印任何内容。为什么它不起作用?我希望它为每个onNext()
调用启动一个新线程,并doOnNext()
打印该线程的名称。现在,我也没有看到任何其他调度程序。
当我在main的末尾添加对Thread.sleep(10000L)
的调用时,我可以看到输出,这表明RxJava使用的线程都是守护进程。是这样的吗?可以以某种方式更改,但使用自定义ThreadFactory或类似的概念,而不必实现自定义调度程序?
通过上述更改,线程名称始终为RxNewThreadScheduler-1
,而newThread的文档为" Scheduler为每个工作单元创建一个新的{@link Thread}
"。是不是应该为所有排放创建一个新线程?
答案 0 :(得分:6)
正如Vladimir所提到的,RxJava标准调度程序在守护程序线程上运行,后者在您的示例中终止,因为主线程退出。我想强调的是,他们没有在新线程上安排每个值,但是他们在新创建的线程上为每个订阅者安排值流。第二次订阅会给你“RxNewThreadScheduler-2”。
您实际上不需要更改默认调度程序,只需使用Schedulers.from()包装您自己的基于Executor的调度程序,并将其作为参数提供给所需的:
ThreadPoolExecutor exec = new ThreadPoolExecutor(
0, 64, 2, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
exec.allowCoreThreadTimeOut(true);
Scheduler s = Schedulers.from(exec);
Observable
.from(Arrays.asList("one", "two", "three"))
.doOnNext(word -> System.out.printf("%s uses thread %s%n", word,
Thread.currentThread().getName()))
.subscribeOn(s)
.subscribe(word -> System.out.println(word));
我有一系列关于RxJava调度程序的blog posts,它们可以帮助您实现“更永久”的变体。
答案 1 :(得分:0)
与新人的看法相反,反应流不是固有并发的,而是固有异步的。它们本质上也是顺序的,并且必须在流中配置并发。简而言之,反应流在其末端自然是顺序的,但在其核心可以并发。
秘密之处在于在流中使用 flatMap()运算符。该运算符从源流中获取一个 Observable
这听起来很复杂(乍看之下很多),但是带有解释的简单示例有助于理解这一概念。
从类似的问题here和有关RxJava2 Schedulers和Concurrency的文章中找到更多详细信息,并提供代码示例以及有关如何依次和同时使用Scheduler的详细说明。
希望这会有所帮助,
Softjake
答案 2 :(得分:0)
public class MainClass {
public static void main(String[] args) {
Scheduler scheduler = Schedulers.from(Executors.newFixedThreadPool(10, Executors.defaultThreadFactory()));
Observable.interval(1,TimeUnit.SECONDS)
.doOnNext(word -> System.out.printf("%s uses thread %s%n", word,
Thread.currentThread().getName()))
.subscribeOn(scheduler)
.observeOn(Schedulers.io())
.doOnNext(word -> System.out.printf("%s uses thread %s%n", word,
Thread.currentThread().getName()))
.subscribe();
}
}