如何在Kotlin中获取协程的名称?

mklgxw1f  于 2023-04-12  发布在  Kotlin
关注(0)|答案(4)|浏览(314)

我很好奇当suspended在主线程上时协程的内部工作。真实的的问题是如何记录suspended函数,它是主线程上的协程。执行到底在哪里发生?它是虚拟线程吗?

frebpwbc

frebpwbc1#

如果您正在讨论记录协程名称:
您可以通过以下方式实现这一点
1.为协程命名(如果你想要自定义名称):launch(CoroutineName("My-Coroutine"))
1.启用IntelliJ工具栏菜单中的日志记录:运行-〉编辑配置并添加
虚拟机选项中的-Dkotlinx.coroutines.debug

然后你可以在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()}

结果:

qybjjes1

qybjjes12#

其他答案没有直接回答“* 如何在Kotlin中获得协程的名称?*”;相反,他们建议如何命名协程。
如果在协程中,可以使用currentCoroutineContext()[CoroutineName]检索名称。
如果在协程之外,没有直接的方法使用JobDeferred的引用来检索名称(太糟糕了)。但是,可以使用反射黑客。当然,通常的警告是,没有类型安全和黑客入侵可能随时更改的内部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

cidc1ykv

cidc1ykv3#

您可以在创建协程时使用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
soat7uwm

soat7uwm4#

您可以像其他人提到的那样使用CoroutineName(“some name”)
要打印CoroutineName,有两种方法:
方法A
System.setProperty("kotlinx.coroutines.debug", "on" )将使Job.toString()包含名称
例如

"my coroutine#4":StandaloneCoroutine{Active}@b735e2c

方法B
在每个作用域中,打印CoroutineContext.toString()将包含名称
例如

CoroutineContext: [CoroutineName(my coroutine), StandaloneCoroutine{Active}@b735e2c, DefaultDispatcher]

方法C
与方法B非常相似,对于Job对象,我们可以打印(Job as CoroutineScope).coroutineContext

相关问题