【发布时间】:2019-06-16 14:29:43
【问题描述】:
当suspended 在主线程上时,我很好奇协程的内部工作。真正的问题是如何记录一个suspended 函数,它是主线程上的协程。执行的具体地点在哪里?是虚拟线程吗?
【问题讨论】:
当suspended 在主线程上时,我很好奇协程的内部工作。真正的问题是如何记录一个suspended 函数,它是主线程上的协程。执行的具体地点在哪里?是虚拟线程吗?
【问题讨论】:
如果你说的是记录协程名称:
你可以通过
来实现为协程命名(如果您想要自定义名称):launch(CoroutineName("My-Coroutine"))
在 IntelliJ 工具栏菜单中启用日志记录:运行 -> 编辑配置并添加
-Dkotlinx.coroutines.debug 在 VM 选项中。
然后就可以在logcat中看到@My-Coroutine了。
编辑配置更改后尝试以下代码:
fun main() = runBlocking {
println(" 'runBlocking': I'm working in thread ${Thread.currentThread().name}")
val job = launch(CoroutineName("my-custom-name")) {
println(" 'runBlocking': I'm working in thread ${Thread.currentThread().name}")
}
job.join()}
【讨论】:
您可以在创建协程时使用CoroutineName(name:String) 方法为协程命名:
repeat(5) {
GlobalScope.launch(CoroutineName("$it")) {
displayGreetingsFor(it)
}
}
要检索协程的名称,请使用coroutineContext[CoroutineName.Key],如下所示:
private suspend fun displayGreetingsFor(i: Int) {
delay(100)
println(
" ${coroutineContext[CoroutineName.Key]} is executing on thread : ${Thread.currentThread().name}"
)
}
这将在控制台上打印以下 o/p:
CoroutineName(0) is executing on thread : DefaultDispatcher-worker-3
CoroutineName(1) is executing on thread : DefaultDispatcher-worker-2
CoroutineName(2) is executing on thread : DefaultDispatcher-worker-8
CoroutineName(3) is executing on thread : DefaultDispatcher-worker-6
CoroutineName(4) is executing on thread : DefaultDispatcher-worker-5
【讨论】:
其他答案没有直接回答问题“如何在 Kotlin 中获取协程的名称?”;相反,他们建议如何命名协程。
如果在协程中,可以使用currentCoroutineContext()[CoroutineName] 检索名称。
如果在协程之外,则没有直接的方法可以使用对 Job 或 Deferred 的引用来检索名称(太糟糕了)。但是,有一个可以使用的反射技巧。当然,还会附上通常的警告,即没有类型安全性和入侵可能随时更改的内部 API。
@Suppress("UNCHECKED_CAST")
val nameString = AbstractCoroutine::class.memberFunctions
.single { it.name == "nameString" } as Function1<AbstractCoroutine<*>, String>
val name = nameString(job as AbstractCoroutine<*>)
.replace("\"", "")
.takeWhile { it != '#' }
包含此代码的方法/函数必须标有@InternalCoroutinesApi。
【讨论】: