如何在没有InterruptedException的情况下处理RxJava中的处置

时间:2019-05-30 16:38:56

标签: java rx-java rx-java2 interrupted-exception

在下面的代码中,当调用dispose()时,代码被截断了,然后发射器线程被中断({InterruptedException被退出睡眠方法)。

    Observable<Integer> obs = Observable.create(emitter -> {
        for (int i = 0; i < 10; i++) {
            if (emitter.isDisposed()) {
                System.out.println("> exiting.");
                emitter.onComplete();
                return;
            }

            emitter.onNext(i);
            System.out.println("> calculation = " + i);


            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        emitter.onComplete();
    });

    Disposable disposable = obs
            .subscribeOn(Schedulers.computation())
            .subscribe(System.out::println);

    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    disposable.dispose();

从调试会话中,我看到中断来自FutureTask,该中断在处置期间被取消。在那里,正在对运行线程检查正在调用dispose()的线程,如果不匹配,则发射器被中断。由于我使用的是计算Scheduler,因此线程是不同的。

是否有任何方法可以处理而不中断这样的发射器,或者这实际上应该始终如何处理?我看到的这种方法的问题是,当我有一个可中断的操作(在这里通过睡眠模拟)时,我希望在调用onComplete()之前可以正常完成该操作。

1 个答案:

答案 0 :(得分:1)

请参阅What's different in 2.0 - Error handling

  

2.x的一项重要设计要求是不得吞下任何Throwable错误。这意味着由于下游的生命周期已经达到其终端状态或下游取消了将要发出错误的序列而无法发出的错误。

因此,您可以将所有内容包装在try / catch中,并正确发出错误:

Observable<Integer> obs = Observable.create(emitter -> {
   try {
      // ...
   } catch (InterruptedException ex) {
      // check if the interrupt is due to cancellation
      // if so, no need to signal the InterruptedException
      if (!disposable.isDisposed()) {
         observer.onError(ex);
      }
   }
});

或设置全局错误使用者以将其忽略:

RxJavaPlugins.setErrorHandler(e -> {
    // ..
    if (e instanceof InterruptedException) {
        // fine, some blocking code was interrupted by a dispose call
        return;
    }
    // ...
    Log.warning("Undeliverable exception received, not sure what to do", e);
});