概念:
輕量級的線程
協程允許我們在單線程模式下模擬多線程編程的效果,代碼執行時的掛起與恢復完
全是由編程語言來控制的,和操作系統無關。這種特性使得高並發程序的運行效率得到了極大的提升。
依賴庫:
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)
}
}