在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
如您所见,当主线程退出时,协程中的代码不再运行。看来科特林会在引擎盖下终止所有协程。
有人能告诉我在主线程退出时协程到底发生了什么吗?
答案 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()
的协同程序行为与提交给它的“经典”任务不同。执行程序将确保所有提交的任务在关闭之前都已完成,但它不考虑挂起的协程。