Kotlin第八阶段学习内容详情

Kotlin 第八阶段学习内容详情:协程入门

本阶段目标是理解 Kotlin 协程的基础用法,能写出简单异步任务。协程内容比较重要,也比较容易一开始觉得抽象,所以本阶段只追求「能看懂、能写简单示例」,不急着深入底层原理。

建议用时:5-7 天。

阶段目标

  • 知道协程解决什么问题。
  • 能理解 suspend 函数的含义。
  • 能使用 runBlocking 运行入门示例。
  • 能使用 launch 启动协程。
  • 能使用 asyncawait 获取异步结果。
  • 初步理解 Dispatchers
  • 初步理解结构化并发。

学习前说明

在普通 Kotlin 项目中使用协程,需要添加 kotlinx-coroutines-core 依赖。Android 项目或部分模板可能已经配置好。

Gradle Kotlin DSL 示例:

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
}

如果你的项目版本不同,以项目已有配置为准。

第 1 天:协程是什么

1. 直观理解

协程可以帮助你写异步代码,比如:

  • 模拟网络请求。
  • 读取文件。
  • 等待数据库返回。
  • 同时执行多个耗时任务。

协程不是线程,但它可以让异步代码写起来像同步代码一样清楚。

2. 第一个协程示例

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

fun main() = runBlocking {
    println("开始")
    delay(1000)
    println("结束")
}

delay(1000) 表示挂起 1000 ms,它不会像 Thread.sleep() 那样直接阻塞线程。

3. runBlocking

runBlocking 会创建一个协程作用域,并阻塞当前线程直到里面的协程执行完。它适合写学习示例和测试代码。

实际业务代码中不会到处写 runBlocking

第 2 天:suspend 函数

1. 什么是 suspend

suspend 表示这个函数可以挂起。

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

suspend fun fetchUserName(): String {
    delay(1000)
    return "Alice"
}

fun main() = runBlocking {
    val name = fetchUserName()
    println(name)
}

2. suspend 函数在哪里调用

suspend 函数只能在协程中或另一个 suspend 函数中调用。

错误写法:

suspend fun fetchData(): String {
    return "data"
}

fun main() {
    fetchData() // 错误
}

正确写法:

import kotlinx.coroutines.runBlocking

suspend fun fetchData(): String {
    return "data"
}

fun main() = runBlocking {
    println(fetchData())
}

第 3 天:launch

1. 启动一个协程

import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    launch {
        delay(1000)
        println("协程任务完成")
    }

    println("主流程继续")
}

2. 多个 launch

import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    launch {
        delay(1000)
        println("任务 1 完成")
    }

    launch {
        delay(500)
        println("任务 2 完成")
    }

    println("等待任务完成")
}

launch 适合启动没有返回值的任务。

第 4 天:asyncawait

1. 获取异步结果

async 适合启动有返回值的任务。

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

suspend fun getPrice(): Int {
    delay(1000)
    return 100
}

suspend fun getCount(): Int {
    delay(1000)
    return 3
}

fun main() = runBlocking {
    val priceDeferred = async { getPrice() }
    val countDeferred = async { getCount() }

    val total = priceDeferred.await() * countDeferred.await()
    println("总价:$total")
}

2. 对比顺序执行

fun main() = runBlocking {
    val price = getPrice()
    val count = getCount()

    println(price * count)
}

顺序执行大约需要 2 秒,并发执行大约需要 1 秒。

第 5 天:Dispatchers

1. Dispatchers 是什么

Dispatchers 用于指定协程运行在哪类线程上。

常见类型:

Dispatcher 常见用途
Dispatchers.Default CPU 计算任务
Dispatchers.IO 文件、网络、数据库等 IO 任务
Dispatchers.Main Android 主线程

2. 示例

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    launch(Dispatchers.Default) {
        println("执行计算任务")
    }

    launch(Dispatchers.IO) {
        println("执行 IO 任务")
    }
}

普通命令行项目里不一定有 Dispatchers.Main,Android 项目中更常见。

第 6 天:结构化并发入门

1. 父协程等待子协程

import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    launch {
        delay(500)
        println("子任务完成")
    }

    println("父作用域中")
}

runBlocking 会等待里面启动的子协程完成。

2. coroutineScope

import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

suspend fun loadData() = coroutineScope {
    launch {
        delay(500)
        println("加载用户")
    }

    launch {
        delay(800)
        println("加载订单")
    }
}

fun main() = runBlocking {
    loadData()
    println("全部加载完成")
}

综合练习

练习 1:模拟网络请求

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

suspend fun fetchMessage(): String {
    delay(1000)
    return "请求成功"
}

fun main() = runBlocking {
    println("开始请求")
    val message = fetchMessage()
    println(message)
}

练习 2:并发加载用户和订单

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

suspend fun fetchUser(): String {
    delay(1000)
    return "Alice"
}

suspend fun fetchOrders(): List<String> {
    delay(1000)
    return listOf("订单 1", "订单 2")
}

fun main() = runBlocking {
    val userDeferred = async { fetchUser() }
    val ordersDeferred = async { fetchOrders() }

    val user = userDeferred.await()
    val orders = ordersDeferred.await()

    println("用户:$user")
    println("订单:$orders")
}

练习 3:多个任务顺序对比

自己写两个版本:

  • 版本 1:顺序调用 2 个 suspend 函数。
  • 版本 2:用 async 并发调用 2 个 suspend 函数。

观察执行时间差异。

必须掌握清单

常见错误

1. 在普通函数中直接调用 suspend

suspend fun fetchData(): String = "data"

fun main() {
    fetchData() // 错误
}

2. 用 launch 期待返回值

launch 不直接返回业务结果。如果需要结果,用 async

3. 在学习示例之外滥用 runBlocking

runBlocking 适合示例和测试,不适合在业务代码中随手包一层。

阶段复盘问题

  1. 协程解决什么问题?
  2. suspend 是什么意思?
  3. launchasync 有什么区别?
  4. await() 的作用是什么?
  5. Dispatchers.IO 适合什么任务?
  6. 什么是结构化并发?
posted @ 2026-06-30 10:58  呢哇哦比较  阅读(2)  评论(0)    收藏  举报