HOWTO · Kotlin

在 Kotlin 中建立和執行協程

本教程向讀者介紹協程,並展示如何在 Kotlin 中使用 async-await() 順序或併發執行它們。

本頁內容

本教程將介紹協程並展示如何在 Kotlin 中使用 async- await() 順序或同時執行它們。

Kotlin 中的協程

協程可以被視為一個過程,除了它支援非同步程式設計與其他僅支援同步程式設計的普通過程相比。

非同步程式設計是一種技術,我們可以在某個點暫停任務的執行,並將執行委託給另一個任務,因為暫停的任務等待一些後臺任務執行。這些後臺任務可以包括從資料庫讀取記錄、下載網頁內容以及處理來自應用程式的使用者請求。

在同步程式設計中,任務的執行在任何時候都不會掛起,執行緒是獨佔使用的,直到執行完成。

一個協程代表這個暫停的例程的例項。它也可以被視為一個執行緒,但是協程不依賴於底層執行緒,因為它可以在不同的執行緒上暫停和恢復執行。

在本教程中,我們將學習如何通過確保 async- await() 函式以正確的順序執行來建立順序和併發協同程式。

在 Kotlin 中建立一個新專案並新增依賴項

轉到 IntelliJ 並選擇 檔案 > 新建 > 專案。在開啟的視窗中,輸入 kotlinCoroutines 作為專案名稱,在 Language 部分選擇 Kotlin,在 Build System 部分選擇 Gradle,然後按 Create 按鈕。

要在 Kotlin 中使用協程,我們必須將協程依賴項新增到我們的應用程式中。轉到檔案 build.gradle.kts 並確保你具有以下依賴項。

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.2")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.2")
    testImplementation(kotlin("test"))
}

確保你具有活動的 Internet 連線以下載依賴項。下載依賴項後,載入 Gradle 更改並繼續執行後續步驟。

在 Kotlin 中按順序建立和執行協程

在 kotlin 資料夾下建立包 com/coroutine,這將是我們應用程式的基礎包。在 coroutine 資料夾下建立一個 Main.kt 檔案,並將以下程式碼複製並貼上到該檔案中。

package com.coroutine

import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

suspend fun executeProcedureOne(): Int{
    delay(3000L)
    println("procedure one executed")
    return 50;
}

suspend fun executeProcedureTwo(): Int{
    delay(1000L)
    println("procedure two executed")
    return 30;
}

fun main(): Unit = runBlocking {
    val value = async {
        executeProcedureOne()
    }
    value.await()
    val secondValue = async {
        executeProcedureTwo()
    }
    secondValue.await()
}

在上面的程式碼中,我們定義了兩個方法,executeProcedureOne() 和 executeProcedureTwo(),可以暫停執行一些後臺任務。這是使用 suspend 關鍵字實現的,如上所示。

請注意,這兩種方法可以在不阻塞底層執行緒的情況下掛起。

我們已將 main 函式分配給名為 runBlocking 的函式。runBlocking 函式是一個構建器函式,它建立一個在主執行緒上執行的協程並被阻塞,直到函式內的協程完成執行。

在 runBlocking 函式中,我們建立了兩個 async 函式,它們分別呼叫 executeProcedureOne() 和 executeProcedureTwo() 方法。

async 函式是一個協程構建器,它建立一個新的協程並返回一個 Deferred。Deferred 是一個代表返回值的承諾的未來,我們可以使用 await() 來檢索該值。

請注意,在 async 之後立即呼叫 await() 將導致協程暫停,因為內部協程正在執行並在完成後恢復。

上面的程式碼在每個 async 函式強制協程暫停直到它完成並且可以轉到其他協程之後,作為 await() 方法順序執行。

執行上面的程式碼,注意 executeProcedureOne() 在 executeProcedureTwo() 之前完成,即使它延遲了最長時間。輸出如下圖所示。

procedure one executed
procedure two executed

在 Kotlin 中同時建立和執行協程

註釋前面的程式碼,然後將下面的程式碼複製並貼上到註釋後的 Main.kt 檔案中。

suspend fun executeProcedureOne(): Int{
    delay(3000L)
    println("procedure one executed")
    return 50;
}

suspend fun executeProcedureTwo(): Int{
    delay(1000L)
    println("procedure two executed")
    return 30;
}

suspend fun executeProcedures() = coroutineScope{
    val firstValue = async {
        executeProcedureOne()
    }

    val secondValue = async {
        executeProcedureTwo()
    }

    firstValue.await()
    secondValue.await()
}

fun main(): Unit = runBlocking  {
    executeProcedures()
}

我們已經將前面的示例修改為併發,通過在函式執行後將 async 協程構建器移動到另一個具有 coroutineScope 和 await() 的可掛起函式,以防止掛起協程。

coroutineScope 和 runBlocking 之間的區別在於 coroutineScope 被掛起並釋放底層執行緒以繼續執行其他任務。

執行上面的程式碼並注意 executeProcedureTwo() 方法首先執行,因為它比 executeProcedureOne() 方法具有更少的延遲。輸出如下所示。

procedure two executed
procedure one executed

まとめ

在本教程中,我們瞭解了協程是什麼以及如何利用 async- await() 函式順序或同時執行它們。我們還學習了協程上下文中的幾個常見概念,包括非同步程式設計、同步程式設計、runBlocking{} 函式和 coroutineScope{} 函式。