我正在使用Rxjava2 ambArray运算符。我创建了2个可观察的实验。
可观察1:
Observable<String> observable1 =
Observable.defer(new Callable<ObservableSource<? extends String>>() {
@Override
public ObservableSource<? extends String> call() throws Exception {
return Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(final ObservableEmitter<String> emitter) throws Exception {
long sleepTime = getRandomNumber();
Log.i(TAG, "Oservable1 : Sleep: " + sleepTime + " Thread: " + Thread.currentThread().getName());
Thread.sleep(sleepTime);
emitter.onNext( "From Observable1 Result" );
emitter.onComplete();
}
})
.subscribeOn(Schedulers.newThread() );
}
});
可观察2:
Observable<String> observable2 =
Observable.defer(new Callable<ObservableSource<? extends String>>() {
@Override
public ObservableSource<? extends String> call() throws Exception {
return Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(final ObservableEmitter<String> emitter) throws Exception {
long sleepTime = getRandomNumber();
Log.i(TAG, "Oservable2 : Sleep: " + sleepTime + " Thread: " + Thread.currentThread().getName());
Thread.sleep(sleepTime);
emitter.onNext("From Observable2 Result" );
emitter.onComplete();
}
})
.subscribeOn(Schedulers.newThread());
}
});
getRandomNumber
方法:
private long getRandomNumber() {
return (long) (Math.random() * 100);
}
我正在创建一个随机延迟以返回String
。
ambArray:
Observable.ambArray(observable1, observable2)
.subscribeOn(Schedulers.io())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i(TAG, "Result : " + s);
}
});
这导致我java.lang.InterruptedException
。
当我从observables sleep
删除ambArray
时,工作正常。如果我手动创建一个新线程然后使用睡眠,这也可以正常工作。
使用手动线程重新编写Observable:
Observable<String> observable1 =
Observable.defer(new Callable<ObservableSource<? extends String>>() {
@Override
public ObservableSource<? extends String> call() throws Exception {
return Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(final ObservableEmitter<String> emitter) throws Exception {
new Thread(new Runnable() {
@Override
public void run() {
long sleepTime = getRandomNumber();
Log.i(TAG, "Oservable1 : Sleep: " + sleepTime + " Thread: " + Thread.currentThread().getName());
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
emitter.onNext( "From Observable1 Result" );
emitter.onComplete();
}
}).start();
}
})
/* .subscribeOn(Schedulers.newThread() )*/;
}
});
如果我在两个可观察中以这种方式使用Thread,它可以正常工作。
为什么使用Schedulers
线程导致Exception
?为什么手动使用线程不会导致任何Exception
?有什么区别?
修改
Logcat:
W/System.err: java.lang.InterruptedException
W/System.err: at java.lang.Thread.sleep(Native Method)
W/System.err: at java.lang.Thread.sleep(Thread.java:1031)
W/System.err: at java.lang.Thread.sleep(Thread.java:985)
W/System.err: at com.yousuf.shawon.rxandroidsamples.fragments.AmdExampleFragment$5$1.subscribe(AmdExampleFragment.java:306)
W/System.err: at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:40)
W/System.err: at io.reactivex.Observable.subscribe(Observable.java:11442)
W/System.err: at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
W/System.err: at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:571)
W/System.err: at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
W/System.err: at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W/System.err: at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
W/System.err: at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
W/System.err: at java.lang.Thread.run(Thread.java:818)
答案 0 :(得分:1)
使用Scheduler
,后备线程池会记住哪个线程正在为休眠的方法提供服务,并且可以在取消时中断它。使用普通的Thread
s,你的引用就会丢失,你还没有将它们连接到取消机制:
@Override
public void subscribe(final ObservableEmitter<String> emitter) throws Exception {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
long sleepTime = getRandomNumber();
Log.i(TAG, "Oservable1 : Sleep: " + sleepTime +
" Thread: " + Thread.currentThread().getName());
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
emitter.onNext( "From Observable1 Result" );
emitter.onComplete();
}
});
t.start();
emitter.setCancellable(() -> t.interrupt());
}