Kotlin 使用協程編寫高效的並發程序


概念:

輕量級的線程

協程允許我們在單線程模式下模擬多線程編程的效果,代碼執行時的掛起與恢復完
全是由編程語言來控制的,和操作系統無關。這種特性使得高並發程序的運行效率得到了極大的提升。

依賴庫:

dependencies {
...
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1"
}
fun main() {
GlobalScope.launch {
println("codes run in coroutine scope")
}
Thread.sleep(1000)
}

借助runBlocking函數實現在協程中所有代碼執行完后再結束:

fun main() {
runBlocking {
println("codes run in coroutine scope")
delay(1500)
println("codes run in coroutine scope finished")
}
}

多個協程

子協程的特點是如果外層作用域的協程結束了,該作用域下的所有子協程也會一同結束。相比而言,GlobalScope.launch函數創建的永遠是頂層協程,這一點和線程比較像,因為線程也沒有層級這一說,永遠都是頂層的。

fun main() {
    runBlocking {
        launch {
        println("launch1")
        delay(1000)
        println("launch1 finished")
    }
    launch {
        println("launch2")
        delay(1000)
        println("launch2 finished")
        }
    }
}

suspend掛起函數關鍵字

suspend關鍵字只能將一個函數聲明成掛起函數,是無法給它提供協程作用域的。

suspend fun printDot() {
    println(".")
    delay(1000)
}

coroutineScope掛起函數

coroutineScope函數和runBlocking函數還有點類似,它可以保證其作用域內的所
有代碼和子協程在全部執行完之前,外部的協程會一直被掛起。

suspend fun printDot() = coroutineScope {
    launch {
        println(".")
        delay(1000)
    }
}

fun main() {
    //協程作用域
    runBlocking {
        //子協程
        coroutineScope {
            launch {
                for (i in 1..10) {
                    println(i)
                    delay(1000)
                }
            }
        }
        println("coroutineScope finished")
    }
    println("runBlocking finished")
}

coroutineScope和runBlocking的區別

coroutineScope函數只會阻塞當前協程,既不影響其他協程,也不影響任何線程,因此是不
會造成任何性能上的問題的。

runBlocking函數由於會掛起外部線程,如果你恰好又在主線程中當中調用它的話,那么就有可能會導致界面卡死的情況,所以不?推薦在實際項目中使用。

實際項目中協程的使用

val job = Job()
val scope = CoroutineScope(job)
scope.launch {
	// 處理具體的邏輯
}
//取消協程
job.cancel()

async函數 創建協程並獲取執行結果

async函數必須在協程作用域當中才能調用,它會創建一個新的子協程並返回一個Deferred對
象,如果我們想要獲取async函數代碼塊的執行結果,只需要調用Deferred對象的await()方法即可

fun main() {
    runBlocking {
        val start = System.currentTimeMillis()
        val deferred1 = async {
            delay(1000)
            5 + 5
        }
        val deferred2 = async {
            delay(1000)
            4 + 6
        }
        //兩個async函數同時執行,執行完后調用await()獲取結果
        println("result is ${deferred1.await() + deferred2.await()}.")
        val end = System.currentTimeMillis()
        println("cost ${end - start} milliseconds.")
    }
}

withContext()函數

簡化版的async函數

線程參數

Dispatchers.Default:表示會使用一種默認低並發的線程策略,當你要執行的代碼屬於計算密集型任務時,開啟過高的並發?而可能會影響任務的運行效率。

Dispatchers.IO:表示會使用一種較高並發的線程策略,當你要執行的代碼大多數時間是在阻塞和等待中,比如說執行網絡請求時,為了能夠支持更高的並發數量。
Dispatchers.Main:不會開啟子線程,而是在Android主線程中執行代碼,但是這個值只能在Android項目中使用,純Kotlin程序使用這種類型的線程參數會出現錯誤。

fun main() {
    runBlocking {
        val result = withContext(Dispatchers.Default) {
        5 + 5
    }
    println(result)
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM