RxJava Thread.sleep()中断异常
我正在使用RxJava(自定义缓存可观察)进行一些工作,发现了以下问题 这个例子很简单:创建可观察的订阅者,并立即取消订阅RxJava Thread.sleep()中断异常,java,rx-java,Java,Rx Java,我正在使用RxJava(自定义缓存可观察)进行一些工作,发现了以下问题 这个例子很简单:创建可观察的订阅者,并立即取消订阅 public static void main(String[] args) { Observable<Long> origin = Observable.create(new Observable.OnSubscribe<Long>() { @Override public void call(Subscriber<? super L
public static void main(String[] args) {
Observable<Long> origin = Observable.create(new Observable.OnSubscribe<Long>() {
@Override public void call(Subscriber<? super Long> subscriber) {
try {
System.out.println("Starting... > " + Thread.currentThread().getName());
Thread.sleep(3000);
subscriber.onNext(System.currentTimeMillis());
Thread.sleep(200);
subscriber.onCompleted();
System.out.println("Complete...");
} catch(Exception e) {
e.printStackTrace();
subscriber.onError(e);
}
}
});
Subscription sub1 = origin.subscribeOn(Schedulers.newThread()).subscribe(new Observer<Long>() {
@Override public void onCompleted() { }
@Override public void onError(Throwable e) { e.printStackTrace(); }
@Override public void onNext(Long value) {
System.out.println("onNext() > " + value);
}
});
try {
sub1.unsubscribe();
} catch (Exception e) {
e.printStackTrace();
}
try {
System.in.read(); // wait for user input to finish
} catch (IOException e) {
e.printStackTrace();
}
我的问题是:为什么(有时)会发生这种异常?
即使创建了.cache()observable,这种情况也会发生
异常绑定到Observable.OnSubscribe()实现中的第一个线程.sleep()调用我的假设是,只有当主线程到达
sub1.unsubscribe()时,异常才会发生
line before Observable进入睡眠状态,因为正是unsubscribe
调用艰难地唤醒了Observable,因为它删除了订阅的线程origin
这个异常似乎是意料之中的,所以单独处理它,而不是使用onError()方法。我的假设是,只有当主线程到达
sub1.unsubscribe()时,异常才会发生
line before Observable进入睡眠状态,因为正是unsubscribe
调用艰难地唤醒了Observable,因为它删除了订阅的线程origin
此异常似乎是预期的,因此请单独处理,而不是使用onError()方法。您正在尝试取消订阅当前正在运行的事件(
Thread.sleep()
)。您的库显然检测到了这一点,并试图唤醒您的事件以停止它。无论如何,您不应该在代码中依赖Sleep()
。总有更好、更恰当的方法。另外,根据规则,事件应该总是尽可能快
如果您足够快地取消订阅,则不会发生异常:您的活动没有启动,它没有休眠,因此没有异常
尝试将取消订阅延迟一秒钟,它将一直启动,并一直创建异常。您正在尝试取消订阅当前正在运行的事件(
Thread.sleep()
)。您的库显然检测到了这一点,并试图唤醒您的事件以停止它。无论如何,您不应该在代码中依赖Sleep()
。总有更好、更恰当的方法。另外,根据规则,事件应该总是尽可能快
如果您足够快地取消订阅,则不会发生异常:您的活动没有启动,它没有休眠,因此没有异常
尝试将取消订阅延迟一秒钟,它会一直启动,并且也会一直创建异常。启动新线程可能需要一些时间(甚至1毫秒),这会给主线程足够的时间取消订阅,从而取消
subscribeOn
计划的任务。其他时候,线程旋转得如此之快,以至于它开始运行OnSubscribe
代码,该代码现在被unsubscribe调用中断
正如其他人提到的,您应该尽量避免代码中出现休眠,但相反,请使用
延迟设置序列,或者简单地使用调度程序.Worker.schedule()
在一段时间后触发操作。启动新线程可能需要一些时间(甚至1毫秒)这使主线程有足够的时间取消订阅,从而取消subscribeOn
计划的任务。其他时候,线程旋转得如此之快,以至于它开始运行OnSubscribe
代码,该代码现在被unsubscribe调用中断
正如其他人所提到的,您应该尽量避免代码中出现睡眠,但相反,请使用delay
s设置序列,或者简单地使用Scheduler.Worker.schedule()
在一段时间后触发操作
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at org.skendel.Program$1.call(Program.java:23)
at org.skendel.Program$1.call(Program.java:19)
at rx.Observable.unsafeSubscribe(Observable.java:7710)
at rx.internal.operators.OperatorSubscribeOn$1$1.call(OperatorSubscribeOn.java:62)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at org.skendel.Program$1.call(Program.java:23)
at org.skendel.Program$1.call(Program.java:19)
at rx.Observable.unsafeSubscribe(Observable.java:7710)
at rx.internal.operators.OperatorSubscribeOn$1$1.call(OperatorSubscribeOn.java:62)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)