欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Kotlin?launch原理全面分析

 更新時間:2022年11月22日 10:03:58   作者:且聽真言  
在Android開發(fā)中,launch是我們經(jīng)常用的,今天來看看它是什么原理,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧

一、協(xié)程是如何創(chuàng)建的

launch、async 可以創(chuàng)建、啟動新的協(xié)程,那么協(xié)程到底是如何創(chuàng)建的?

  runBlocking {
        println(Thread.currentThread().name)
        launch {
            println(Thread.currentThread().name)
            delay(100L)
        }
        Thread.sleep(1000L)
    }
Log
main @coroutine#1
main @coroutine#2
Process finished with exit code 0

runBlocking{} 啟動了第一個協(xié)程,launch{} 啟動了第二個協(xié)程。

協(xié)程啟動的基礎(chǔ)API

public fun <T> (suspend () -> T).createCoroutine(
    completion: Continuation<T>
): Continuation<Unit> =
    SafeContinuation(createCoroutineUnintercepted(completion).intercepted(), COROUTINE_SUSPENDED)
public fun <T> (suspend () -> T).startCoroutine(
    completion: Continuation<T>
) {
    createCoroutineUnintercepted(completion).intercepted().resume(Unit)
}

createCoroutine{}、startCoroutine{}就是 Kotlin 協(xié)程當中最基礎(chǔ)的兩個創(chuàng)建協(xié)程的 API。啟動協(xié)程有三種常見的方式:launch、runBlocking、async。它們其實屬于協(xié)程中間層提供的 API,而它們的底層都調(diào)用了“基礎(chǔ)層”的協(xié)程 API。

createCoroutine{}、startCoroutine{}是擴展函數(shù),其擴展接收者類型是一個函數(shù)類型:suspend () -> T,代表了“無參數(shù),返回值為 T 的掛起函數(shù)或者 Lambda”。而對于函數(shù)本身,它們兩個都接收一個 Continuation<T> 類型的參數(shù),其中一個函數(shù),還會返回一個 Continuation<Unit> 類型的返回值。

val block = suspend {
    println("Hello")
    delay(1000L)
    println("World!")
    "Result"
}
fun testLaunch2() {
    val continuation = object : Continuation<String> {
        override val context: CoroutineContext
            get() = EmptyCoroutineContext
        override fun resumeWith(result: Result<String>) {
            println("Result:" + result.getOrNull())
        }
    }
    block.startCoroutine(continuation)
}
fun main() {
    testLaunch2()
    Thread.sleep(2000L)
}
Log
Hello
World!
Result:Result
Process finished with exit code 0

類型為suspend () -> T的函數(shù)或者Lambda 表達式可以用 block.startCoroutine() 來啟動協(xié)程了。

Continuation 有兩種用法,一種是在實現(xiàn)掛起函數(shù)的時候,用于傳遞掛起函數(shù)的執(zhí)行結(jié)果;另一種是在調(diào)用掛起函數(shù)的時候,以匿名內(nèi)部類的方式,用于接收掛起函數(shù)的執(zhí)行結(jié)果。

使用 createCoroutine() 這個方法其實上面代碼的邏輯:

fun testLaunch3() {
    val continuation = object : Continuation<String> {
        override val context: CoroutineContext
            get() = EmptyCoroutineContext
        override fun resumeWith(result: Result<String>) {
            println("Result:" + result.getOrNull())
        }
    }
    val coroutinue = block.createCoroutine(continuation)
    coroutinue.resume(Unit)
}
val block = suspend {
    println("Hello")
    delay(1000L)
    println("World!")
    "Result"
}
fun main() {
    testLaunch3()
    Thread.sleep(2000L)
}
Log
Hello
World!
Result:Result
Process finished with exit code 0

createCoroutine() 創(chuàng)建一個協(xié)程,先不啟動。調(diào)用 resume() 才能啟動。createCoroutine()、startCoroutine() 的源代碼差別也并不大,只是前者沒有調(diào)用 resume(),而后者調(diào)用了 resume()。startCoroutine() 之所以可以創(chuàng)建并同時啟動協(xié)程的原因就在于,它在源碼中直接調(diào)用了 resume(Unit)。

將 startCoroutine()轉(zhuǎn)換為Java:

package com.example.myapplication.testcoroutinue;
import kotlin.Metadata;
import kotlin.Result;
import kotlin.ResultKt;
import kotlin.Unit;
import kotlin.coroutines.Continuation;
import kotlin.coroutines.ContinuationKt;
import kotlin.coroutines.CoroutineContext;
import kotlin.coroutines.EmptyCoroutineContext;
import kotlin.coroutines.intrinsics.IntrinsicsKt;
import kotlin.jvm.functions.Function1;
import kotlin.jvm.internal.Intrinsics;
import kotlinx.coroutines.DelayKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@Metadata(
   mv = {1, 6, 0},
   k = 2,
   d1 = {"\u0000\u001e\n\u0000\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0002\u0010\u000e\n\u0002\u0010\u0000\n\u0002\b\u0004\n\u0002\u0010\u0002\n\u0002\b\u0002\u001a\u0006\u0010\b\u001a\u00020\t\u001a\u0006\u0010\n\u001a\u00020\t\",\u0010\u0000\u001a\u0018\b\u0001\u0012\n\u0012\b\u0012\u0004\u0012\u00020\u00030\u0002\u0012\u0006\u0012\u0004\u0018\u00010\u00040\u0001?\u0001\u0000¢\u0006\n\n\u0002\u0010\u0007\u001a\u0004\b\u0005\u0010\u0006\u0082\u0002\u0004\n\u0002\b\u0019¨\u0006\u000b"},
   d2 = {"block", "Lkotlin/Function1;", "Lkotlin/coroutines/Continuation;", "", "", "getBlock", "()Lkotlin/jvm/functions/Function1;", "Lkotlin/jvm/functions/Function1;", "main", "", "testLaunch2", "My_Application.app.main"}
)
public final class TestCoroutinue888Kt {
// Kotlin 為 block 變量生成的靜態(tài)變量
   @NotNull
   private static final Function1 block;
   public static final void main() {
      testLaunch2();
      Thread.sleep(2000L);
   }
   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }
    // Kotlin 為 block 變量生成的靜態(tài)變量以及方法
   @NotNull
   public static final Function1 getBlock() {
      return block;
   }
   public static final void testLaunch2() {
//continuation 變量對應(yīng)的匿名內(nèi)部類
      <undefinedtype> continuation = new Continuation() {
         @NotNull
         public CoroutineContext getContext() {
            return (CoroutineContext)EmptyCoroutineContext.INSTANCE;
         }
         public void resumeWith(@NotNull Object result) {
            String var2 = "Result:" + (String)(Result.isFailure-impl(result) ? null : result);
            System.out.println(var2);
         }
      };
//block.startCoroutine(continuation) 轉(zhuǎn)換成了ContinuationKt.startCoroutine(block, (Continuation)continuation)
      ContinuationKt.startCoroutine(block, (Continuation)continuation);
   }
   static {
    //實現(xiàn)了 Continuation 接口
      Function1 var0 = (Function1)(new Function1((Continuation)null) {
         int label;
//invokeSuspend()為協(xié)程狀態(tài)機邏輯
         @Nullable
         public final Object invokeSuspend(@NotNull Object $result) {
            Object var3 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
            String var2;
            switch(this.label) {
            case 0:
               ResultKt.throwOnFailure($result);
               var2 = "Hello";
               System.out.println(var2);
               this.label = 1;
               if (DelayKt.delay(1000L, this) == var3) {
                  return var3;
               }
               break;
            case 1:
               ResultKt.throwOnFailure($result);
               break;
            default:
               throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
            }
            var2 = "World!";
            System.out.println(var2);
            return "Result";
         }
         @NotNull
         public final Continuation create(@NotNull Continuation completion) {
            Intrinsics.checkNotNullParameter(completion, "completion");
            Function1 var2 = new <anonymous constructor>(completion);
            return var2;
         }
         public final Object invoke(Object var1) {
            return ((<undefinedtype>)this.create((Continuation)var1)).invokeSuspend(Unit.INSTANCE);
         }
      });
      block = var0;
   }
}
public fun <T> (suspend () -> T).startCoroutine(
    completion: Continuation<T>
) {
createCoroutineUnintercepted(completion).intercepted().resume(Unit)
}

在 startCoroutine() 當中,首先會調(diào)用 createCoroutineUnintercepted() 方法。

public expect fun <T> (suspend () -> T).createCoroutineUnintercepted(
    completion: Continuation<T>
): Continuation<Unit>

代碼中的 expect,一種聲明,由于 Kotlin 是面向多個平臺的,具體的實現(xiàn),就需要在特定的平臺實現(xiàn)。

public actual fun <T> (suspend () -> T).createCoroutineUnintercepted(
    completion: Continuation<T>
): Continuation<Unit> {
    val probeCompletion = probeCoroutineCreated(completion)
    return if (this is BaseContinuationImpl)
        create(probeCompletion)
    else
        createCoroutineFromSuspendFunction(probeCompletion) {
            (this as Function1<Continuation<T>, Any?>).invoke(it)
        }
}

actual,代表了 createCoroutineUnintercepted() 在 JVM 平臺的實現(xiàn)。

createCoroutineUnintercepted() 是一個擴展函數(shù),this代表了 block 變量。(this is BaseContinuationImpl) 條件為ture,就會調(diào)用 create(probeCompletion)。

public open fun create(completion: Continuation<*>): Continuation<Unit> {
    throw UnsupportedOperationException("create(Continuation) has not been overridden")
}

在默認情況下,這個 create() 方法是會拋出異常的。

         @NotNull
         public final Continuation create(@NotNull Continuation completion) {
            Intrinsics.checkNotNullParameter(completion, "completion");
            Function1 var2 = new <anonymous constructor>(completion);
            return var2;
         }

返回了Continuation 對象。

public fun <T> (suspend () -> T).startCoroutine(
    completion: Continuation<T>
) {
createCoroutineUnintercepted(completion).intercepted().resume(Unit)
}

intercepted() 在JVM 實現(xiàn)如下:

public actual fun <T> Continuation<T>.intercepted(): Continuation<T> =
    (this as? ContinuationImpl)?.intercepted() ?: this

將 Continuation 強轉(zhuǎn)成了 ContinuationImpl,調(diào)用了它的 intercepted()。

ContinuationImpl 的源代碼:

internal abstract class ContinuationImpl(
    completion: Continuation<Any?>?,
    private val _context: CoroutineContext?
) : BaseContinuationImpl(completion) {
    @Transient
    private var intercepted: Continuation<Any?>? = null
    public fun intercepted(): Continuation<Any?> =
        intercepted
            ?: (context[ContinuationInterceptor]?.interceptContinuation(this) ?: this)
                .also { intercepted = it }
}

通過 ContinuationInterceptor,對 Continuation 進行攔截,從而將程序的執(zhí)行邏輯派發(fā)到特定的線程之上。

resume(Unit):

public fun <T> (suspend () -> T).startCoroutine(
    completion: Continuation<T>
) {
createCoroutineUnintercepted(completion).intercepted().resume(Unit)
}

resume(Unit),作用其實就相當于啟動了協(xié)程。

二、launch 是如何啟動協(xié)程的

fun main() {
    testLaunch11()
    Thread.sleep(2000L)
}
fun testLaunch11() {
    val coroutineScope = CoroutineScope(Job())
    coroutineScope.launch {
        println("Hello")
        delay(1000L)
        println("World!")
    }
}
Log
Hello
World!
Process finished with exit code 0

轉(zhuǎn)Java

package com.example.myapplication.testcoroutinue;
import kotlin.Metadata;
import kotlin.ResultKt;
import kotlin.Unit;
import kotlin.coroutines.Continuation;
import kotlin.coroutines.CoroutineContext;
import kotlin.coroutines.intrinsics.IntrinsicsKt;
import kotlin.jvm.functions.Function2;
import kotlin.jvm.internal.Intrinsics;
import kotlinx.coroutines.BuildersKt;
import kotlinx.coroutines.CoroutineScope;
import kotlinx.coroutines.CoroutineScopeKt;
import kotlinx.coroutines.CoroutineStart;
import kotlinx.coroutines.DelayKt;
import kotlinx.coroutines.Job;
import kotlinx.coroutines.JobKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@Metadata(
   mv = {1, 6, 0},
   k = 2,
   d1 = {"\u0000\n\n\u0000\n\u0002\u0010\u0002\n\u0002\b\u0002\u001a\u0006\u0010\u0000\u001a\u00020\u0001\u001a\u0006\u0010\u0002\u001a\u00020\u0001¨\u0006\u0003"},
   d2 = {"main", "", "testLaunch11", "My_Application.app.main"}
)
public final class TestCoroutinue999Kt {
   public static final void main() {
      testLaunch11();
      Thread.sleep(2000L);
   }
   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }
   public static final void testLaunch11() {
      CoroutineScope coroutineScope = CoroutineScopeKt.CoroutineScope((CoroutineContext)JobKt.Job$default((Job)null, 1, (Object)null));
//對應(yīng) launch 當中的 Lambda。
      BuildersKt.launch$default(coroutineScope, (CoroutineContext)null, (CoroutineStart)null, (Function2)(new Function2((Continuation)null) {
         int label;
         @Nullable
         public final Object invokeSuspend(@NotNull Object $result) {
            Object var3 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
            String var2;
            switch(this.label) {
            case 0:
               ResultKt.throwOnFailure($result);
               var2 = "Hello";
               System.out.println(var2);
               this.label = 1;
               if (DelayKt.delay(1000L, this) == var3) {
                  return var3;
               }
               break;
            case 1:
               ResultKt.throwOnFailure($result);
               break;
            default:
               throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
            }
            var2 = "World!";
            System.out.println(var2);
            return Unit.INSTANCE;
         }
         @NotNull
         public final Continuation create(@Nullable Object value, @NotNull Continuation completion) {
            Intrinsics.checkNotNullParameter(completion, "completion");
            Function2 var3 = new <anonymous constructor>(completion);
            return var3;
         }
         public final Object invoke(Object var1, Object var2) {
            return ((<undefinedtype>)this.create(var1, (Continuation)var2)).invokeSuspend(Unit.INSTANCE);
         }
      }), 3, (Object)null);
   }
}

launch源碼

public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
    //launch 會根據(jù)傳入的 CoroutineContext 創(chuàng)建出新的 Context。
    val newContext = newCoroutineContext(context)
    //launch 會根據(jù)傳入的啟動模式來創(chuàng)建對應(yīng)的協(xié)程對象。這里有兩種,一種是標準的,一種是懶加載的。
    val coroutine = if (start.isLazy)
        LazyStandaloneCoroutine(newContext, block) else
        StandaloneCoroutine(newContext, active = true)
    //啟動協(xié)程。
    coroutine.start(start, coroutine, block)
    return coroutine
}

coroutine.start() :

public abstract class AbstractCoroutine<in T>(
    parentContext: CoroutineContext,
    initParentJob: Boolean,
    active: Boolean
) : JobSupport(active), Job, Continuation<T>, CoroutineScope {
    public fun <R> start(start: CoroutineStart, receiver: R, block: suspend R.() -> T) {
        start(block, receiver, this)
    }
}

AbstractCoroutine.kt 對應(yīng)協(xié)程的抽象邏輯。AbstractCoroutine 的start() 方法,用于啟動協(xié)程。

public enum class CoroutineStart {
    public operator fun <T> invoke(block: suspend () -> T, completion: Continuation<T>): Unit =
        when (this) {
            DEFAULT -> block.startCoroutineCancellable(completion)
            ATOMIC -> block.startCoroutine(completion)
            UNDISPATCHED -> block.startCoroutineUndispatched(completion)
            LAZY -> Unit // will start lazily
        }
}

start(block, receiver, this),進入 CoroutineStart.invoke()。

invoke() 方法當中,根據(jù) launch 傳入的啟動模式,以不同的方式啟動協(xié)程。當啟動模式是 ATOMIC 的時候,就會調(diào)用 block.startCoroutine(completion)。startCoroutineUndispatched(completion) 和 startCoroutineCancellable(completion),只是在 startCoroutine() 的基礎(chǔ)上增加了一些額外的功能而已。前者代表啟動協(xié)程以后就不會被分發(fā),后者代表啟動以后可以響應(yīng)取消。

startCoroutineCancellable(completion)

public fun <T> (suspend () -> T).startCoroutineCancellable(completion: Continuation<T>): Unit = runSafely(completion) {
    createCoroutineUnintercepted(completion).intercepted().resumeCancellableWith(Result.success(Unit))
}
public actual fun <T> (suspend () -> T).createCoroutineUnintercepted(
    completion: Continuation<T>
): Continuation<Unit> {
    val probeCompletion = probeCoroutineCreated(completion)
    return if (this is BaseContinuationImpl)
        create(probeCompletion)
    else
        createCoroutineFromSuspendFunction(probeCompletion) {
            (this as Function1<Continuation<T>, Any?>).invoke(it)
        }
}

startCoroutineCancellable() 的源代碼,會調(diào)用 createCoroutineUnintercepted(),然后調(diào)用 create(probeCompletion),然后最終會調(diào)用create() 方法。launch 這個 API,只是對協(xié)程的基礎(chǔ)元素 startCoroutine() 等方法進行了一些封裝而已。

到此這篇關(guān)于Kotlin launch原理全面分析的文章就介紹到這了,更多相關(guān)Kotlin launch內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論