当主线程退出时协程会发生什么?

Nhấ*_*ang 6 kotlin kotlin-coroutines

在 Java 中,当主线程退出时,所有用户线程(非守护线程)将继续运行,直到它们完成工作。

我有一个简单的程序,可以将 1 到 5 的计数器打印到控制台。

爪哇版:

fun main(args: Array<String>) {
    println("Main start")

    countWithThread()

    println("Main end")
}

fun countWithThread() {
    Thread(Runnable {
        for (i in 1..5) {
            println("${Thread.currentThread().name} count $i")
            Thread.sleep(10)
        }
    }).start()
}
Run Code Online (Sandbox Code Playgroud)

输出:

Main start
Main end
Thread-0 count 1
Thread-0 count 2
Thread-0 count 3
Thread-0 count 4
Thread-0 count 5

Process finished with exit code 0
Run Code Online (Sandbox Code Playgroud)

科特林版本:

fun main(args: Array<String>) {
    println("Main start")

    countWithCoroutine()

    println("Main end")
}

fun countWithCoroutine() {
    launch(CommonPool) {
        for (i in 1..5) {
            println("${Thread.currentThread().name} count $i")
            delay(10)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

Main start
Main end

Process finished with exit code 0
Run Code Online (Sandbox Code Playgroud)

可以看到,当主线程退出时,协程中的代码不再运行。Kotlin 似乎在幕后终止了所有协程。

谁能告诉我主线程退出时协程到底发生了什么?

zsm*_*b13 5

当主线程完成执行并且进程/JVM 实例终止时,协程就会终止,它们就像守护线程一样。请参阅官方协程指南中的这一部分以供参考。


Mar*_*nik 5

协程本身并没有以 JVM 知道的方式“运行”。它们只不过是堆上的对象。

但是,协程上下文在何时允许 JVM 终止方面确实有发言权。创建自己的:

val threadPool = Executors.newFixedThreadPool(4)
val dispatcher = threadPool.asCoroutineDispatcher()
Run Code Online (Sandbox Code Playgroud)

现在,如果您使用它而不是CommonPool:

launch(dispatcher) { ... }
Run Code Online (Sandbox Code Playgroud)

你会发现 JVM 根本没有消亡,即使所有的任务都完成了。只有当你明确说的时候它才会退出

threadPool.shutdown()
Run Code Online (Sandbox Code Playgroud)

但是请注意,这executor.shutdown()对协程的行为与您提交给它的“经典”任务的行为不同。执行器将确保所有提交的任务在关闭之前都完成,但它不会考虑暂停的协程。