【问题标题】:GlobalScope.launch doesn't finish its task inside runBlocking main functionGlobalScope.launch 未在 runBlocking 主函数中完成其任务
【发布时间】:2020-12-09 10:35:06
【问题描述】:

我不明白为什么在下面的程序中GlobalScope.launch 指令没有完成它的任务。

我明白runBlocking 无法控制GlobalScope,而且使用它通常很糟糕,但这并不让我知道为什么GlobalScope.launch {} 中的指令没有按预期执行。

代码sn-p:

package coroutines

import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.io.File

fun main() = runBlocking<Unit> {
    GlobalScope.launch {
        val file = File(javaClass.getResource("/coroutines_file.txt").path)

        file.printWriter().use { out ->
            repeat(10) { i ->
                delay(100)
                out.println(i.toString())
            }
        }
    }
}

coroutines_file 中的预期输出:

0
1
2
3
4
5
6
7
8
9

实际输出:

一个空文件。

【问题讨论】:

标签: kotlin kotlin-coroutines terminate file-writing global-scope


【解决方案1】:

GlobalScope 只是结构化并发的一个逃生口。它无法取消,甚至没有与之关联的Job,因此它没有提供一个顶级工具来跟踪其中启动的所有作业。

另一方面,runBlocking 建立了自己的作用域,您应该为启动的协程继承该作用域,并自动确保所有子协程运行完成。

runBlocking<Unit> {
    launch(Dispatchers.IO) {
        val file = File(javaClass.getResource("/coroutines_file.txt").path)
        file.printWriter().use { out ->
            repeat(10) { i ->
                delay(100)
                out.println(i.toString())
            }
        }
    }
}

【讨论】:

  • 什么会杀死 GlobalScope 进程,为什么?我对 JVM 世界很陌生。我不明白为什么程序会停止,即使有工作要做,即 GlobalScope.launch 中的指令,但它没有完成也没有被告知停止。
  • 协程作用域不是一个进程,它只是一个持有CoroutineContext 的对象,Kotlin 可以轻松地将作用域对象传递到协程层次结构中。具体来说,GlobalScope 定义了一个完全空的CoroutineContext,因此您最终使用了Default 协程调度程序。这映射到 JVM 的全局线程池 ForkJoinPool.commonPool(),并且该线程池使用标记为“守护程序”的线程,这在 Java 中意味着当所有非守护程序线程结束时它会自动终止。
  • 哦,现在我明白了!非常感谢!
  • “其中没有任何设施可以等待其中启动的作业完成”有点令人困惑。听起来你甚至不能在.join() Jobs launched 里面 GlobalScope
猜你喜欢
  • 2019-07-17
  • 2019-08-28
  • 1970-01-01
  • 2013-02-03
  • 2016-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-05
相关资源
最近更新 更多