Kotlin 协程 (一)

1. Kotlin 协程的核心概念

1.1 协程(Coroutine)
  • 定义:协程是一种轻量级的执行上下文,可以在任何时候挂起和恢复,而不需要阻塞线程。
  • 特点
    • 比传统线程更轻量,开销更小。
    • 支持挂起和恢复,避免了阻塞线程和资源浪费。
    • 提供更简洁的并发编程方式。
1.2 挂起函数(Suspend Function)
  • 定义 :使用 suspend 关键字修饰的函数,可以在协程中挂起执行,挂起期间不会阻塞线程。
  • 作用:允许协程在等待任务完成时释放线程资源,待任务完成后恢复执行。
1.3 协程作用域(Coroutine Scope)
  • 定义:协程作用域定义了协程的生命周期,确保协程在作用域结束时被取消。
  • 常见作用域
    • GlobalScope:全局作用域,生命周期与整个应用程序一致(不推荐用于实际开发)。
    • CoroutineScope:自定义作用域,可通过 CoroutineScope(Dispatchers) 创建。
    • runBlocking:用于测试场景,会阻塞当前线程直到协程完成。
1.4 协程构建器(Coroutine Builders)
  • launch:启动一个协程,不返回结果。
  • async :启动一个协程,并返回一个 Deferred 对象,可用于获取结果。
  • runBlocking:阻塞当前线程,直到协程完成(仅用于测试)。

2. Kotlin 协程的使用方法

以下是协程使用的基本步骤:

2.1 添加依赖项

在项目的 build.gradle 文件中添加 Kotlin 协程库依赖:

复制代码
dependencies {
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
}
2.2 创建协程作用域

协程必须在协程作用域中运行。例如:

Kotlin 复制代码
import kotlinx.coroutines.*

fun main() = runBlocking { // 用于测试,实际开发中避免使用
    val scope = CoroutineScope(Dispatchers.Default)
    scope.launch {
        // 在这里执行异步任务
    }
}
2.3 启动协程

使用 launchasync 启动协程:

  • launch:用于不需要返回结果的异步任务。
  • async:用于需要返回结果的异步任务。
Kotlin 复制代码
scope.launch {
    delay(1000L) // 模拟耗时操作
    println("异步任务完成")
}

val deferred = scope.async {
    delay(1000L)
    "异步任务结果"
}
println("异步任务返回值: ${deferred.await()}")
2.4 使用挂起函数

挂起函数允许协程在等待任务时挂起,例如 delay

Kotlin 复制代码
suspend fun fetchData(): String {
    delay(1000L) // 模拟网络请求
    return "Data fetched"
}

3. Kotlin 协程的具体示例

以下通过几个常见场景展示协程的实际用法。

3.1 简单的异步任务

使用 launch 启动一个异步任务:

Kotlin 复制代码
import kotlinx.coroutines.*

fun main() = runBlocking {
    launch {
        delay(1000L)
        println("World!")
    }
    println("Hello,")
}
  

输出:
Hello,
World!
3.2 并行任务与结果获取

使用 asyncawait 实现并行任务:

Kotlin 复制代码
import kotlinx.coroutines.*

fun main() = runBlocking {
    val deferred1 = async {
        fetchDataFromNetwork1()
    }
    val deferred2 = async {
        fetchDataFromNetwork2()
    }
    println("Data1: ${deferred1.await()}")
    println("Data2: ${deferred2.await()}")
}

suspend fun fetchDataFromNetwork1(): String {
    delay(1000L)
    return "NetworkData1"
}

suspend fun fetchDataFromNetwork2(): String {
    delay(1000L)
    return "NetworkData2"
}
3.3 取消协程

使用 cancel 方法取消协程:

Kotlin 复制代码
import kotlinx.coroutines.*

fun main() = runBlocking {
    val job = launch {
        delay(5000L)
        println("Task completed")
    }
    delay(1000L)
    job.cancel()
    println("Coroutine cancelled")
}

4.实际应用示例

网络请求与数据库操作

Kotlin 复制代码
// 假设有以下挂起函数
suspend fun fetchUserData(): UserData = withContext(Dispatchers.IO) {
    // 模拟网络请求
    delay(1000)
    UserData("John", 30)
}

suspend fun saveToDatabase(user: UserData) = withContext(Dispatchers.IO) {
    // 模拟数据库操作
    delay(500)
    println("User saved: $user")
}

data class UserData(val name: String, val age: Int)

fun main() = runBlocking {
    // 顺序执行
    val user = fetchUserData()
    saveToDatabase(user)
    
    // 并发执行多个网络请求
    val users = listOf("user1", "user2", "user3")
    val deferredList = users.map { userId ->
        async { fetchUserDataForId(userId) }
    }
    val results = deferredList.awaitAll()
    println("All users fetched: $results")
}

suspend fun fetchUserDataForId(userId: String): UserData {
    delay(1000)
    return UserData("$userId-Name", 20 + userId.last().digitToInt())
}

5. 总结

  • 核心概念:协程、挂起函数、协程作用域和协程构建器是协程编程的基础。
  • 使用方法:通过添加依赖、创建作用域、启动协程和使用挂起函数,可以轻松实现异步编程。
  • 适用场景:协程适用于网络请求、文件 IO、CPU 密集型任务等需要并发处理的场景。
相关推荐
lsnm5 分钟前
【LINUX操作系统】生产者消费者模型(下):封装、信号量与环形队列
linux·运维·服务器·开发语言·c++·ubuntu·centos
谢尔登11 分钟前
【Umi】项目初始化配置和用户权限
开发语言·javascript·ecmascript
chao_78911 分钟前
python八股文汇总(持续更新版)
开发语言·python·学习
爱喝水的鱼丶15 分钟前
SAP-ABAP:SAP的BAPI_PO_CHANGE功能详解
开发语言·sap·abap·bapi·采购订单修改
未来之窗软件服务20 分钟前
在 Excel 中使用东方仙盟软件————仙盟创梦IDE
开发语言·excel·excel插件·仙盟创梦ide
炯哈哈1 小时前
【上位机——WPF】命名空间
开发语言·windows·c#·wpf·上位机
Yan_ks2 小时前
JAVA面向对象——对象和类的基本语法
java·开发语言
云手机管家2 小时前
自动化脚本开发:Python调用云手机API实现TikTok批量内容发布
android·网络安全·智能手机·架构·自动化
Paddy哥2 小时前
jsmpeg+java+ffmpeg 调用摄像头RTSP流播放
java·开发语言·ffmpeg