在Eclipse下测试Rxjava中的操作符interval()时出现了很奇怪的问题,怎么试都不能执行。

代码如下:

Observable.interval(1, TimeUnit.SECONDS)
.subscribe(new Subscriber<Long>() {

@Override
public void onCompleted() {
// TODO Auto-generated method stub
System.out.println("onCompleted ");
}

@Override
public void onError(Throwable arg0) {
// TODO Auto-generated method stub

}

@Override
public void onNext(Long arg0) {
// TODO Auto-generated method stub
System.out.println("onNext "

这段代码在Eclipse下面运行没有达到我们预期的每隔一秒输出一个数字的结果。

怎么解决呢?

去官网找了下原因,也找到了解决方案:
​​​https://github.com/ReactiveX/RxJava/issues/3932​

Observable.interval(1, TimeUnit.SECONDS)
.subscribe(new Subscriber<Long>() {

@Override
public void onCompleted() {
// TODO Auto-generated method stub
System.out.println("onCompleted ");
}

@Override
public void onError(Throwable arg0) {
// TODO Auto-generated method stub

}

@Override
public void onNext(Long arg0) {
// TODO Auto-generated method stub
System.out.println("onNext " + arg0);
}
});

try {
Thread.sleep(20000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block

这样就能输出结果了如下所示:

onNext 0
onNext 1
onNext 2
onNext 3
onNext 4
onNext 5
onNext 6

让程序沉睡一段时间似乎也不是很完美的解决方案,继续找就找到了如下的解决办法(​​https://github.com/ReactiveX/RxJava/issues/4132​​)。

具体原因如下:

When you use the default scheduler (Schedulers.computation()) the observable emits on another thread. If your program exits just after the subscribe then the observable is not given a chance to run. Put in a long sleep just after the subscribe() call and you will see it working.

最终代码如下:

Observable.interval(1, TimeUnit.SECONDS, Schedulers.trampoline())
.subscribe(new Subscriber<Long>() {

@Override
public void onCompleted() {
// TODO Auto-generated method stub
System.out.println("onCompleted ");
}

@Override
public void onError(Throwable arg0) {
// TODO Auto-generated method stub

}

@Override
public void onNext(Long arg0) {
// TODO Auto-generated method stub
System.out.println("onNext "

需要注意的是,上面代码中的 Schedulers.trampoline()替换为Schedulers.immediate()也是可以运行的,但是这样做是不安全的。

The immediate() scheduler is not safe for recursive scheduling on the current thread, use trampoline() instead.

Schedulers.computation() 与 Schedulers.trampoline()区别

首先我们看看源码:

/**
* Creates and returns a {@link Scheduler} that executes work immediately on the current thread.
*
* @return
public static Scheduler immediate() {
return rx.internal.schedulers.ImmediateScheduler.INSTANCE;
}

/**
* Creates and returns a {@link Scheduler} that queues work on the current thread to be executed after the
* current work completes.
*
* @return
public static Scheduler trampoline() {
return

从上面源码可以看出,immediate()方法返回的是ImmediateScheduler类的实例,而trampoline()方法返回的是TrampolineScheduler类的实例。

ImmediateScheduler类的部分源码:

/**
* Executes work immediately on the current thread.
*/
public final class ImmediateScheduler extends Scheduler
public static final ImmediateScheduler INSTANCE = new ImmediateScheduler();

private ImmediateScheduler() {
// the class is singleton

从ImmediateScheduler类的官网介绍中可以看出ImmediateScheduler执行在当前main线程。

TrampolineScheduler类的部分源码:

/**
* Schedules work on the current thread but does not execute immediately. Work is put in a queue and executed
* after the current unit of work is completed.
*/
public final class TrampolineScheduler extends Scheduler
public static final TrampolineScheduler INSTANCE = new TrampolineScheduler();

@Override
public Worker createWorker() {
return new

从TrampolineScheduler类的官网介绍中可以看出TrampolineScheduler不会立即执行,当其他排队任务介绍时才执行,当然TrampolineScheduler运行在当前main线程。

了解调度器

调度器的种类

下表展示了RxJava中可用的调度器种类:

调度器类型

效果

Schedulers.computation( )

用于计算任务,如事件循环或和回调处理,不要用于IO操作(IO操作请使用Schedulers.io());默认线程数等于处理器的数量

Schedulers.from(executor)

使用指定的Executor作为调度器

Schedulers.immediate( )

在当前线程立即开始执行任务

Schedulers.io( )

用于IO密集型任务,如异步阻塞IO操作,这个调度器的线程池会根据需要增长;对于普通的计算任务,请使用Schedulers.computation();Schedulers.io( )默认是一个CachedThreadScheduler,很像一个有线程缓存的新线程调度器

Schedulers.newThread( )

为每个任务创建一个新线程

Schedulers.trampoline( )

当其它排队的任务完成后,在当前线程排队开始执行

默认调度器

在RxJava中,某些Observable操作符的变体允许你设置用于操作执行的调度器,其它的则不在任何特定的调度器上执行,或者在一个指定的默认调度器上执行。下面的表格个列出了一些操作符的默认调度器:

操作符

调度器

buffer(timespan)

computation

buffer(timespan, count)

computation

buffer(timespan, timeshift)

computation

debounce(timeout, unit)

computation

delay(delay, unit)

computation

delaySubscription(delay, unit)

computation

interval

computation

repeat

trampoline

replay(time, unit)

computation

replay(buffersize, time, unit)

computation

replay(selector, time, unit)

computation

replay(selector, buffersize, time, unit)

computation

retry

trampoline

sample(period, unit)

computation

skip(time, unit)

computation

skipLast(time, unit)

computation

take(time, unit)

computation

takeLast(time, unit)

computation

takeLast(count, time, unit)

computation

takeLastBuffer(time, unit)

computation

takeLastBuffer(count, time, unit)

computation

throttleFirst

computation

throttleLast

computation

throttleWithTimeout

computation

timeInterval

immediate

timeout(timeoutSelector)

immediate

timeout(firstTimeoutSelector, timeoutSelector)

immediate

timeout(timeoutSelector, other)

immediate

timeout(timeout, timeUnit)

computation

timeout(firstTimeoutSelector, timeoutSelector, other)

immediate

timeout(timeout, timeUnit, other)

computation

timer

computation

timestamp

immediate

window(timespan)

computation

window(timespan, count)

computation

window(timespan, timeshift)

computation


了解更多Scheduler使用请参考:
​​​https://github.com/mcxiaoke/RxDocs/blob/master/Scheduler.md​