本文從協(xié)程的啟動launch
源碼入手分析,協(xié)程JVM實現(xiàn)分為兩篇:
- 協(xié)程啟動和執(zhí)行源碼分析
- 無棧協(xié)程 和 Continuation
基本環(huán)境:
- IntelliJ IDEA 2023.3.2
- Kotlin 1.8.20
- kotlinx-coroutines-core 1.7.3
- gradle 8.2
一、協(xié)程的啟動和執(zhí)行
以 GlobalScope.launch
啟動協(xié)程分析:
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyStandaloneCoroutine(newContext, block) else
StandaloneCoroutine(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}
調用關系:CoroutineScope.launch
-> StandaloneCoroutine.start
->CoroutineStart.invoke
-> block.startCoroutineCancellable
。
1. startCoroutineCancellable 啟動流程
啟動協(xié)程,默認 執(zhí)行 block.startCoroutineCancellable
擴展方法:
internal fun <R, T> (suspend (R) -> T).startCoroutineCancellable(
receiver: R, completion: Continuation<T>,
onCancellation: ((cause: Throwable) -> Unit)? = null
) =
runSafely(completion) {
createCoroutineUnintercepted(receiver, completion).intercepted().resumeCancellableWith(Result.success(Unit), onCancellation)
}
說明:
-
createCoroutineUnintercepted
, 創(chuàng)建 Continuation; -
intercepted
,攔截生成 DispatchedContinuation; -
resumeCancellableWith
,調度器 派發(fā) 執(zhí)行協(xié)程。
intercepted()
關鍵在 intercepted()
方法:
- 獲取
ContinuationInterceptor
,默認值是Dispatchers.Default
, - 使用
CoroutineDispatcher.interceptContinuation
生成DispatchedContinuation
// ContinuationImpl 攔截方法
@Transient
private var intercepted: Continuation<Any?>? = null
public fun intercepted(): Continuation<Any?> =
intercepted
?: (context[ContinuationInterceptor]?.interceptContinuation(this) ?: this)
.also { intercepted = it }
// Dispatchers.Default 源碼
public final override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> =
DispatchedContinuation(this, continuation)
resumeCancellableWith
DispatchedContinuation.resumeCancellableWith
實現(xiàn)了 調度器(線程池)的任務 派發(fā),也就是 Runnable
:
inline fun resumeCancellableWith(
result: Result<T>,
noinline onCancellation: ((cause: Throwable) -> Unit)?
) {
val state = result.toState(onCancellation)
if (dispatcher.isDispatchNeeded(context)) {
_state = state
resumeMode = MODE_CANCELLABLE
dispatcher.dispatch(context, this)
} else {
executeUnconfined(state, MODE_CANCELLABLE) {
if (!resumeCancelled(state)) {
resumeUndispatchedWith(result)
}
}
}
}
默認執(zhí)行到:dispatcher.dispatch(context, this)
,此時調度器 派發(fā) 執(zhí)行。DispatchedContinuation
實現(xiàn)了 Runnable
接口, run()
調用即開始執(zhí)行階段,接下來分析。
2. DispatchedContinuation
DispatchedContinuation
繼承DispatchedTask
,委托了Contanuation
。
協(xié)程的最終執(zhí)行:
DispatchedContinuation.resumeCancellableWith
-> dispatcher.dispatch()
-> DispatchedTask.run()
-> DispatchedContinuation.continuation.resumeWith
。
最終 DispatchedContinuation.continuation
也就是我們 launch {}
塊生成的 SuspendLambda
類對象。
ContinuationImpl
無論是
launch {}
塊生成的SuspendLambda
類,還是suspend fun
函數(shù) 生成ContinuationImpl
匿名類。
它們都 繼承BaseContinuationImpl
。
基類 BaseContinuationImpl
,實現(xiàn)了 resumeWith
:
try {
val outcome = invokeSuspend(param)
if (outcome === COROUTINE_SUSPENDED) return
Result.success(outcome)
} catch (exception: Throwable) {
Result.failure(exception)
}
調用了 抽象 invokeSuspend
,也就是 launch {}
塊編譯后的代碼。
執(zhí)行完成后,會執(zhí)行 協(xié)程 completion.resumeWith(outcome)
,最終完成。
resumeWith -> onCompletionInternal -> onCompleted 或 onCancelled
launch {} 塊編譯代碼分析
launch {}
和 async {}
編譯后,都繼承 SuspendLambda
。
反編譯.class
,通過 jadx-gui
看到 塊 代碼一般是下面 形式:文章來源:http://www.zghlxwxcb.cn/news/detail-805562.html
public static final class AnonymousClass1 extends SuspendLambda implements Function2<CoroutineScope, Continuation<? super Unit>, Object> {
int label;
@NotNull
public final Continuation<Unit> create(@Nullable Object value, @NotNull Continuation<?> continuation) {
return new AnonymousClass1(continuation);
}
@Nullable
public final Object invoke(@NotNull CoroutineScope p1, @Nullable Continuation<? super Unit> continuation) {
return create(p1, continuation).invokeSuspend(Unit.INSTANCE);
}
@Nullable
public final Object invokeSuspend(@NotNull Object $result) {
// launch {} 執(zhí)行代碼塊 邏輯,會編譯到這里
...
}
}
小結
通過launch
啟動協(xié)程源碼分析,了解了:文章來源地址http://www.zghlxwxcb.cn/news/detail-805562.html
- Dispatchers 調度器何時派發(fā)任務
- 協(xié)程 Continuation 掛起、執(zhí)行 和 恢復
補充類圖
Continuation
DispatchedContinuation
關鍵類和文件
- kotlin.coroutines.Continuation.kt
- kotlin.coroutines.CoroutineContext
-
kotlin.coroutines.jvm.internal.BaseContinuationImpl.kt 對應
Continuation
默認實現(xiàn)。 - kotlinx.coroutines.CoroutineStart 啟動線程方式、調用
文檔
- kotlin coroutines
- kotlin KEEP | Offcial
- Advanced coroutines concepts | Android
- 分析Kotlin協(xié)程實現(xiàn)原理
- 探索 Kotlin 協(xié)程原理
- KotlinConf 2017 - Deep Dive into Coroutines on JVM
- Koltin 協(xié)程(非阻塞式掛起)實現(xiàn)原理(五)
- kotlinx-coroutines-core 1.7.3源碼
- https://doordash.engineering/2021/11/09/the-beginners-guide-to-kotlin-coroutine-internals/
- CancellableContinuationImpl.kt
到了這里,關于Kotlin協(xié)程的JVM實現(xiàn)源碼分析(上)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!