Kotlin中的并发与多线程:从理论到实践
现代应用程序需要快速且响应迅速。无论是从网络加载数据、处理大型数组还是与用户界面交互——都离不开并发和多线程。Kotlin作为面向JVM、Android和多平台项目的现代语言,提供了灵活的解决方案。在本文中,我们将分析关键方法:从经典线程到轻量级协程,并展示如何编写高效代码。
1. Kotlin中的线程(Threads):经典方法
线程是继承自Java的并行执行基本机制。在Kotlin中,您可以像在Java中一样创建线程,但语法更简洁。
启动线程的简单示例:
fun main() { thread { println("线程已启动:${Thread.currentThread().name}") Thread.sleep(1000) println("线程已结束") } println("主线程:${Thread.currentThread().name}") Thread.sleep(2000)}然而,线程存在缺点:它们很重(每个线程消耗约1 MB内存),数量有限,且上下文切换成本高昂。对于拥有数千个并行任务的现代应用程序来说,线程并非最佳选择。这正是协程发挥作用的地方。
2. 协程(Coroutines):轻量级替代方案
协程是Kotlin用于并发的核心特性。它们在线程之上运行,但消耗更少的资源。一个线程可以执行数千个协程,无需阻塞即可暂停和恢复它们。
要开始使用,请在build.gradle.kts中添加依赖项:
dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")}简单协程示例:
import kotlinx.coroutines.*
fun main() = runBlocking { launch { delay(1000L) // 非阻塞延迟 println("来自协程的世界!") } println("来自主协程的问候") delay(2000L)}这里launch启动一个新的协程,而delay在不阻塞线程的情况下暂停它。runBlocking用于阻塞主线程直到所有协程完成(通常仅在main和测试中使用)。
2.1. 挂起函数(Suspend-functions)
suspend关键字允许在不阻塞线程的情况下暂停函数的执行。这是Kotlin中异步编程的基础。
suspend fun fetchUser(): String { delay(500L) // 模拟网络请求 return "User123"}
fun main() = runBlocking { val user = fetchUser() println("获取到用户:$user")}2.2. 用于并行任务的Async和Deferred
如果需要并行执行多个任务并等待其结果,请使用async和Deferred:
fun main() = runBlocking { val time = measureTimeMillis { val user = async { fetchUser() } val profile = async { fetchProfile() } println("结果:${user.await()}, ${profile.await()}") } println("执行时间:$time 毫秒")}
suspend fun fetchUser(): String { delay(500) return "User"}
suspend fun fetchProfile(): String { delay(500) return "Profile"}两个任务并行执行,从而减少了总时间。
3. 协程调度器(Dispatchers)
调度器决定了协程将在哪些线程上执行。主要类型:
Dispatchers.Default— 用于CPU密集型任务(默认)。Dispatchers.IO— 用于输入/输出操作(网络、文件)。Dispatchers.Main— 用于UI线程(Android, JavaFX)。 ```