簡體   English   中英

如何在 Kotlin 中獲取協程的名稱?

[英]How to get the name of a coroutine in Kotlin?

我很好奇協程在主線程上suspended時的內部工作。 真正的問題是如何在主線程上記錄作為協程的suspended函數。 執行究竟發生在哪里? 是虛擬線程嗎?

如果您正在談論記錄協程名稱:

你可以通過

  1. 給協程命名(如果你想要自定義名稱): launch(CoroutineName("My-Coroutine"))

  2. 在 IntelliJ 工具欄菜單中啟用日志記錄:運行 -> 編輯配置並添加

-Dkotlinx.coroutines.debug在 VM 選項中。

編輯配置中的 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()}

結果: 結果

其他答案沒有直接回答問題“如何在 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標記。

您可以在創建協程時使用CoroutineName(name:String)方法為協程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

以下是來自docs的示例,我猜這是最接近你可以得到的。

import kotlinx.coroutines.*

fun main() = runBlocking<Unit> {
    launch { // context of the parent, main runBlocking coroutine
        println("main runBlocking      : I'm working in thread ${Thread.currentThread().name}")
    }
    launch(Dispatchers.Unconfined) { // not confined -- will work with main thread
        println("Unconfined            : I'm working in thread ${Thread.currentThread().name}")
    }
    launch(Dispatchers.Default) { // will get dispatched to DefaultDispatcher 
        println("Default               : I'm working in thread ${Thread.currentThread().name}")
    }
    launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
        println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}")
    }    
}

會印這個。

Unconfined            : I'm working in thread main
Default               : I'm working in thread DefaultDispatcher-worker-1
newSingleThreadContext: I'm working in thread MyOwnThread
main runBlocking      : I'm working in thread main

在這里閱讀更多

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM