You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

toBlockingFirst()方法可靠性问询:dispose时是否触发InterruptedException崩溃

Is RxJava's blockingFirst() Reliable? Will It Throw InterruptedException on Dispose?

Great question—let's unpack this step by step, including your specific code scenario.

Core Questions Answered

1. Is blockingFirst() reliable?

Yes, but only if you use it appropriately. This blocking method will:

  • Wait synchronously until the source Observable emits its first item, then return that item immediately.
  • Throw NoSuchElementException if the Observable completes without emitting any items.
  • Propagate any errors emitted by the source Observable.

When the associated Disposable is disposed, blockingFirst() will terminate immediately:

  • If no item was emitted yet, it throws IllegalStateException (indicating the sequence was cancelled).
  • If an item was already emitted, it returns that item normally.

2. Will calling dispose() trigger an InterruptedException and crash?

No, not by default. InterruptedException is thrown only when the thread executing blockingFirst() is explicitly interrupted (e.g., via Thread.currentThread().interrupt()). Calling dispose() on the subscription does not directly interrupt the thread—it simply cancels the Observable sequence, which causes blockingFirst() to terminate with an IllegalStateException (if no item was emitted) rather than an interrupt.

That said, if your code manually interrupts the thread running blockingFirst(), you will need to handle InterruptedException to avoid crashes.

Issues with Your Example Code

Your current code uses blockingFirst() inside a flatMap operator, which is a problematic practice:

.flatMap{ host ->
    val count = userRepository.getUsers(PrefProvider.currentTourCode)
        .map { it.size }
        .blockingFirst()
    if (count>2) {
        callSomething()
    } else {
        callElse()
    }
}
  • Blocking inside flatMap (which runs on a RxJava scheduler thread) will block that thread, potentially starving the scheduler's thread pool, causing performance issues, or even deadlocks.
  • This defeats the purpose of RxJava's reactive, non-blocking paradigm.

Rewrite your logic to use RxJava's reactive operators instead of blocking:

.flatMap{ host ->
    userRepository.getUsers(PrefProvider.currentTourCode)
        .map { it.size }
        .flatMap { count ->
            if (count > 2) {
                // Assume callSomething() returns an Observable/Maybe/Single
                callSomething()
            } else {
                // Assume callElse() returns an Observable/Maybe/Single
                callElse()
            }
        }
}

If callSomething() and callElse() are not reactive (i.e., they return void or a non-Rx type), use doOnNext to handle the side effects while keeping the stream non-blocking:

.flatMap{ host ->
    userRepository.getUsers(PrefProvider.currentTourCode)
        .map { it.size }
        .doOnNext { count ->
            if (count > 2) {
                callSomething()
            } else {
                callElse()
            }
        }
}

Final Takeaways

  • blockingFirst() is reliable for specific use cases (e.g., integrating reactive code with legacy synchronous code), but avoid using it within RxJava's operator chain.
  • Calling dispose() won't trigger InterruptedException, but you should handle IllegalStateException and NoSuchElementException to prevent unexpected crashes.
  • Always prefer reactive operators over blocking calls to maintain RxJava's performance and non-blocking benefits.

内容的提问来源于stack exchange,提问作者Serg Burlaka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:23:56