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

时间:2018-09-06 03:41:11

标签: kotlin kotlin-coroutines

在Java中,当主线程退出时,所有用户线程(非守护程序线程)将一直运行,直到完成工作为止。

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

Java版本:

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()
}

输出:

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

科特林版本:

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)
        }
    }
}

输出:

Main start
Main end

Process finished with exit code 0

如您所见,当主线程退出时,协程中的代码不再运行。看来科特林会在引擎盖下终止所有协程。

有人能告诉我在主线程退出时协程到底发生了什么吗?

2 个答案:

答案 0 :(得分:2)

当主线程完成执行并且进程/ JVM实例死亡时,协程终止,它们就像守护程序线程一样。请参阅官方协程指南中的this section

答案 1 :(得分:2)

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

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

val threadPool = Executors.newFixedThreadPool(4)
val dispatcher = threadPool.asCoroutineDispatcher()

现在,如果您使用它代替CommonPool

launch(dispatcher) { ... }

您会发现,即使完成所有任务,JVM也不会消失。仅当您明确地说出

时,它才会退出
threadPool.shutdown()

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