我需要保留对 Disposable 的引用吗

Do I need to keep the reference to a Disposable

如果我有一个很长的运行(它需要很长时间才能发出唯一的信号)Mono并且我订阅了它,我会得到一个Disposable作为return值。我是否必须在某处保留对 Disposable 实例的引用,以便 Mono 能够完成其工作?如果我不必存储使订阅引用保持活动状态的 Disposable 实例,为什么它不会意外地被垃圾收集?

我问是因为我来自 RxSwift 和 iOS 世界,在那里人们会存储这样的 Disposable 实例并在某个时候清理那些一次性用品。订阅 class 将存储一次性实例,并在 deinit 上调用 cancel Disposable

如果你不使用它,你就不需要持有参考。

反应器的概念与线程非常相似。当你启动一个线程时,它会完成它的工作并在之后退出(即使你没有持有对它的引用)。当然,如果它是守护线程并且所有非守护线程都已退出(因此程序已完成),它可能会抛出异常或被杀死。

当您的应用程序处于活动状态时,不保留引用不是问题,因为反应器流就像一些方法调用,运行在调用者或不同线程上调用,线程的堆栈将保留所有必要的参考资料。

当您创建一个流时,默认它将在调用者线程上 运行。 例如这里它将打印所有数字然后退出程序。流将在主线程(调用者)上发出项目,因此主线程无法退出,直到流 运行ning:

fun main() {
    Flux.just(1,2,3,4,5,6,7,8,9).doOnNext { println(it) }.subscribe()
}

当您更改发射器线程,并且它是守护线程时,应用程序将立即退出,因为它在与主线程不同的线程上发射项目,并且没有什么可以阻止主线程退出。不会打印任何内容。

fun main() {
    Flux.just(1,2,3,4,5,6,7,8,9)
        .doOnNext { println(it) }
        .subscribeOn(Schedulers.boundedElastic())
        .subscribe()
}

但是如果你使用 nondeamon,它会打印数字:

val executorService = Executors.newFixedThreadPool(1) {
    val thread = Executors.defaultThreadFactory().newThread(it)
    thread.isDaemon = false
    thread
}

fun main() {
    Flux.just(1, 2, 3, 4, 5, 6, 7, 8, 9)
        .doOnNext { println(it) }
        .subscribeOn(Schedulers.fromExecutorService(executorService))
        //.subscribeOn(Schedulers.boundedElastic())
        .subscribe()
    println("After subscribe")
    //The executorService should be shut down here
}

当您使用网络服务器(如 netty)时,它将保持应用程序 运行ning,因此反应流可以运行直到服务器关闭。

请注意,这是反应器的简化。我想您应该阅读文档和 java 线程来完全理解这个主题。