我们在前面章回中介绍了RxJava的观察者,被观察者,事件流以及操作符,这些都是RxJava的主要特点,本章回中将介绍RxJava的另外一个特点:多线程操作。
我们在Java中使用多线程时会使用Thread类,Runnable接口,以及线程池相关的类,RxJava把这些类和接口进行了封装,然后的提供相应的操作符来实现多线程,常用的操作符是:subscribeOn
()和observeOn
(),以及与它们配合使用的Schedulers
类。
使用subscribeOn
()和observeOn
()操作符来创建子线程.它们的使用方法和just
()等操作符的使用方法类似,不过这两个方法需要Schedulers类型的参数,通过该参数可以创建不同的线程。
Schedulers
类提供了一些静态方法来创建线程:newThread
()方法用来创建一个新的子线程,io()
方法用来创建一个无限量大的线池。
多线程操作很难通过文字进行表达,因此通过文本结合代码的方式来介绍如何创建子线程来实现多线程操作。
Log.d(TAG, "rxAndroidEx: "+Thread.currentThread());
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(@io.reactivex.rxjava3.annotations.NonNull ObservableEmitter<String> emitter) throws Throwable {
Log.d(TAG, "subscribe: " + Thread.currentThread());
emitter.onNext("Event 1");
emitter.onNext("Event 2");
emitter.onComplete();
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Throwable {
Log.d(TAG, "Observer accept: " + s + " " + Thread.currentThread());
}
});
上面的代码演示了一个RxJava基本的操作,我们先打印了程序所在的线程名,然后分别打印了被观察者和观察者所在的线程名,程序的运行结果如下:
rxAndroidEx: Thread[main,5,main] //所有代码所有在线程
subscribe: Thread[main,5,main] //观察者所在的线程
Observer accept: Event 1 Thread[main,5,main] //被观察者所在的线程
Observer accept: Event 2 Thread[main,5,main] //被观察者所在的线程
从程序的运行结果可以看到,所有程序都在一个线程中运行,我们在subscribe()方法的上一行添加以下代码来创建一个子线程:
.subscribeOn(Schedulers.newThread())
.subscribe(new Consumer<String>() {
我们只列出了有差异的代码,其它代码没有列出来,编译并且运行修改后的程序可以得到以下运行结果:
rxAndroidEx: Thread[main,5,main] //所有代码所有在线程
subscribe: Thread[RxNewThreadScheduler-2,5,main] //观察者所在的线程与主线程不一样
Observer accept: Event 1 Thread[RxNewThreadScheduler-2,5,main] //被观察者所在的线程与主线程不一样
Observer accept: Event 2 Thread[RxNewThreadScheduler-2,5,main] //被观察者所在的线程与主线程不一样
从程序的运行结果中可以看到观察者和被观察者在所在的线程是一个新的子线程:RxNewThreadScheduler-2,
而主线程位于线程main
中,从中可以看出这是两个线程,也就是说我们在主线程中使用RxJava创建了一个新的线程。
上面的程序中,我们使用subscribeOn
()方法创建了一个子线程,接下来我们使用observeOn
()方法来创建子线程:把上面程序中的subscirbeOn
()方法修改为observeOn
()方法(这两个操作符的使用方法相同),详细如下:
.observeOn(Schedulers.newThread())
.subscribe(new Consumer<String>() {
编译并且并且运行修改后的程序可以得到以下结果:
rxAndroidEx: Thread[main,5,main] //所有代码所有在线程
subscribe: Thread[main,5,main] //观察者所在的线程与主线程一样
Observer accept: Event 1 Thread[RxNewThreadScheduler-2,5,main] //被观察者所在的线程与主线程不一样
Observer accept: Event 2 Thread[RxNewThreadScheduler-2,5,main] //被观察者所在的线程与主线程不一样
从程序的运行结果中可以看到,程序中有两个线程:被观察者在主线程main中运行,观察者在子线程RxNewThreadScheduler-2
中运行。
我们使用subscribeOn和observeOn这两个操作符创建了子线程,他们的使用的方法完全相同,不过它们创建线程的时机不同,或者对RxJava事件流的影响不同。
我们以代码中使用操作符的位置为界,位于操作符前面的代码称作事件的上游,位于操作符后面的代码称作事件的下游。observeOn
操作符会在事件下游创建创建子线程,或者说位于下游中的事件会在子线程中运行。subscribeOn
操作符会在事件的上游创建子线程,或者说位于上游中的事件会在子线程中运行。
此外,还有一个默认规则需要注意:如果下游中没有创建子线程,那么下游中的事件和上游中的事件使用相同的线程。比如我们使用subscribeOn
操作符创建子线程时就是这种情况:上游中的被观察者位于子线程中,因为下游中没有创建子线程,所以位于下游中的观察者和位于上游中的被观察者位于相同的线程中。我们通过代码来演示:
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.newThread())
.subscribe(new Consumer<String>() {
我们在subscribe这行代码前面同时使用了两个操作符来创建线程,编译并且运行修改后的程序可以得到以下结果:
rxAndroidEx: Thread[main,5,main] //所有代码所有在线程
subscribe: Thread[RxNewThreadScheduler-1,5,main] //观察者所在的线程为子线程1,与主线程不一样
Observer accept: Event 1 Thread[RxNewThreadScheduler-2,5,main] //被观察者所在的线程为子线程2,与主线程不一样
Observer accept: Event 2 Thread[RxNewThreadScheduler-2,5,main] //被观察者所在的线程为子线程2,与主线程不一样
从程序中的运行结果可以看到程序中有三个线程在运行:代码所在的主线程main,被观察者和观察者所在的子线程分别是:RxNewThreadScheduler-1和2.
看官们,关于"RxJava中的多线程操作"的例子咱们就介绍到这里,欲知后面还有什么例子,且听下回分解!