Kotlin協程的啟動方式介紹

啟動協程的基本方式

1.GlobalScope.launch

代碼示例:

fun testGlobalScope() {
    GlobalScope.launch {
        println("Coroutinue started!")
        delay(1000L)
        println("Hello World!")
    }
    println("After launch!")
    Thread.sleep(2000L)
    println("Process end!")
}
/**
 * After launch!
 * Coroutinue started!
 * Hello World!
 * Process end!
 */
@DelicateCoroutinesApi
public object GlobalScope : CoroutineScope {
    /**
     * Returns [EmptyCoroutineContext].
     */
    override val coroutineContext: CoroutineContext
        get() = EmptyCoroutineContext
}
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
}

launch函數是CoroutineScope的擴展函數,它有三個參數:

  • context: CoroutineContext = EmptyCoroutineContext, 第一個參數是協程上下文,它的默認值是 EmptyCoroutineContext,如果不傳這個參數,默認就會使用 EmptyCoroutineContext。也可以傳入 Kotlin 官方為我們提供的 Dispatchers,來指定協程運行的線程池。(Dispatchers.IO、Dispatchers.Unconfined、Dispatchers.Main)
  • start: CoroutineStart = CoroutineStart.DEFAULT,第二個參數是協程的啟動模式,默認值是CoroutineStart.DEFAULT,CoroutineStart 是一個枚舉類,一共有:DEFAULT、LAZY、ATOMIC、UNDISPATCHED。
  • block: suspend CoroutineScope.() -> Unit,第三個參數是函數類型block,它的類型是suspend CoroutineScope.() -> Unit。本質是一個掛起函數。
  • 函數的返回值是一個 Job,它其實代表的是協程的句柄,並不能返回協程的執行結果。

2.runBlocking 啟動協程

代碼示例

fun testRunBlocking2() {
    runBlocking {
        println("Coroutinue started!")
        delay(1000L)
        println("Hello World!")
    }
    println("After Launch")
    Thread.sleep(2000L)
    println("Process end")
}
/**
 * Coroutinue started!
 * Hello World!
 * After Launch
 * Process end
 */
@Throws(InterruptedException::class)
public actual fun <T> runBlocking(context: CoroutineContext, block: suspend CoroutineScope.() -> T): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    val currentThread = Thread.currentThread()
    val contextInterceptor = context[ContinuationInterceptor]
    val eventLoop: EventLoop?
    val newContext: CoroutineContext
    if (contextInterceptor == null) {
        // create or use private event loop if no dispatcher is specified
        eventLoop = ThreadLocalEventLoop.eventLoop
        newContext = GlobalScope.newCoroutineContext(context + eventLoop)
    } else {
        // See if context's interceptor is an event loop that we shall use (to support TestContext)
        // or take an existing thread-local event loop if present to avoid blocking it (but don't create one)
        eventLoop = (contextInterceptor as? EventLoop)?.takeIf { it.shouldBeProcessedFromContext() }
            ?: ThreadLocalEventLoop.currentOrNull()
        newContext = GlobalScope.newCoroutineContext(context)
    }
    val coroutine = BlockingCoroutine<T>(newContext, currentThread, eventLoop)
    coroutine.start(CoroutineStart.DEFAULT, coroutine, block)
    return coroutine.joinBlocking()
}

runBlocking是普通函數,第一個參數:context: CoroutineContext,協程上下文。第二個參數是函數類型,block: suspend CoroutineScope.() -> T,函數類型是有返回值類型 T 的,與 runBlocking 的返回值類型是一樣的,runBlocking 其實是可以從協程當中返回執行結果的。

fun testRunBlocking() {
    val runBlockingResult = runBlocking {
        delay(500L)
        return@runBlocking "HaHa"
    }
    println("result:$runBlockingResult")
}
result:HaHa

runBlocking特點:

runBlocking 啟動的協程會阻塞當前線程的執行。

3.async啟動協程

使用 async{} 創建協程,可以通過它返回的Deferred拿到協程的執行結果。

代碼示例

fun testAsync() {
    runBlocking {
        val deferred = async {
            println("do async:${Thread.currentThread().name}")
            delay(1000L)
            return@async "do completed"
        }
        println("After async:${Thread.currentThread().name}")
        val result = deferred.await()
        println("Result is: $result")
    }
}
After async:main @coroutine#1
do async:main @coroutine#2
Result is: do completed
public fun <T> CoroutineScope.async(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> T
): Deferred<T> {
    val newContext = newCoroutineContext(context)
    val coroutine = if (start.isLazy)
        LazyDeferredCoroutine(newContext, block) else
        DeferredCoroutine<T>(newContext, active = true)
    coroutine.start(start, coroutine, block)
    return coroutine
}

async註意點

  • async 啟動協程以後,不會阻塞當前程序的執行流程。
  • async{}的返回值,是一個 Deferred 對象,它的 await() 方法,就可以拿到協程的執行結果。
  • await隻是等待執行完,並不是觸發執行。

到此這篇關於Kotlin協程的啟動方式介紹的文章就介紹到這瞭,更多相關Kotlin協程啟動內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: