一些 Kotlin 多线程开发的实际例子,特别关注 IntelliJ 插件开发场景。
1. 协程基础示例
import kotlinx.coroutines.*
// 基础协程使用
fun basicCoroutineExample() {
// 启动主协程作用域
runBlocking {
// 启动后台任务
val job = launch(Dispatchers.IO) {
println("后台任务开始执行,线程: ${Thread.currentThread().name}")
delay(2000) // 非阻塞延迟
println("后台任务执行完毕")
}
// 等待任务完成
job.join()
println("所有任务已完成")
}
}
// 并行执行多个任务
suspend fun parallelExecutionExample() {
val time = measureTimeMillis {
// 并行执行三个任务
val job1 = async(Dispatchers.IO) { fetchData1() }
val job2 = async(Dispatchers.IO) { fetchData2() }
val job3 = async(Dispatchers.IO) { fetchData3() }
// 等待所有结果
val result1 = job1.await()
val result2 = job2.await()
val result3 = job3.await()
println("所有结果: $result1, $result2, $result3")
}
println("总耗时: $time ms")
}
2. IntelliJ 插件中的实际应用
import com.intellij.openapi.application.ApplicationManager
import kotlinx.coroutines.*
// 在 IntelliJ 插件中执行后台任务并更新 UI
class PluginService {
fun performBackgroundOperation() {
// 方法1: 使用协程
GlobalScope.launch(Dispatchers.IO) {
try {
// 执行耗时操作
val result = performHeavyComputation()
// 切换到 UI 线程更新界面
withContext(Dispatchers.Main) {
updateUI(result)
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
showError(e.message ?: "未知错误")
}
}
}
// 方法2: 使用 IntelliJ 的线程管理
ApplicationManager.getApplication().executeOnPooledThread {
try {
val result = performHeavyComputation()
// 更新 UI 必须在 EDT 线程
ApplicationManager.getApplication().invokeLater {
updateUI(result)
}
} catch (e: Exception) {
ApplicationManager.getApplication().invokeLater {
showError(e.message ?: "未知错误")
}
}
}
}
private fun performHeavyComputation(): String {
Thread.sleep(3000) // 模拟耗时操作
return "计算结果"
}
private fun updateUI(result: String) {
// 更新界面组件
println("更新UI: $result")
}
private fun showError(message: String) {
// 显示错误信息
println("错误: $message")
}
}
3. 文件操作示例
import kotlinx.coroutines.*
import java.io.File
class FileProcessingService {
suspend fun processMultipleFiles(filePaths: List<String>): List<String> {
return coroutineScope {
filePaths.map { filePath ->
async(Dispatchers.IO) {
processFile(filePath)
}
}.awaitAll()
}
}
private suspend fun processFile(filePath: String): String {
return withContext(Dispatchers.IO) {
try {
val file = File(filePath)
// 模拟文件处理
delay(1000)
"已处理: ${file.name}"
} catch (e: Exception) {
"处理失败: $filePath"
}
}
}
}
4. 网络请求示例
import kotlinx.coroutines.*
import java.net.URL
class NetworkService {
suspend fun fetchMultipleUrls(urls: List<String>): List<String?> {
return coroutineScope {
urls.map { url ->
async(Dispatchers.IO) {
fetchDataFromUrl(url)
}
}.awaitAll()
}
}
private suspend fun fetchDataFromUrl(urlString: String): String? {
return withContext(Dispatchers.IO) {
try {
val url = URL(urlString)
url.readText()
} catch (e: Exception) {
null
}
}
}
}
5. 生产者-消费者模式
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
class ProducerConsumerExample {
fun demonstrateProducerConsumer() = runBlocking {
val channel = Channel<Int>(Channel.UNLIMITED)
// 生产者
val producer = launch(Dispatchers.IO) {
repeat(10) { i ->
channel.send(i * i)
delay(100)
}
channel.close()
}
// 消费者
val consumer = launch(Dispatchers.IO) {
for (value in channel) {
println("接收到: $value")
delay(200)
}
println("消费完成")
}
joinAll(producer, consumer)
}
}
6. 结合 IntelliJ API 的完整示例
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.Task
import com.intellij.openapi.project.Project
import kotlinx.coroutines.*
class IntellijPluginTask(private val project: Project) : Task.Backgroundable(project, "处理任务") {
override fun run(indicator: ProgressIndicator) {
// 使用协程处理后台任务
runBlocking {
launch(Dispatchers.IO) {
indicator.text = "正在执行任务..."
// 模拟进度更新
for (i in 1..100) {
if (indicator.isCanceled) break
// 执行实际工作
performWorkStep()
// 更新进度
indicator.fraction = i / 100.0
delay(50)
}
// 完成后更新 UI
withContext(Dispatchers.Main) {
ApplicationManager.getApplication().invokeLater {
showCompletionMessage()
}
}
}
}
}
private suspend fun performWorkStep() {
// 模拟工作步骤
delay(10)
}
private fun showCompletionMessage() {
// 显示完成消息
println("任务已完成")
}
}
关键要点总结
-
协程 vs 传统线程:
- 协程更轻量级,启动速度快
- 协程有更好的结构化并发支持
- 协程提供更简洁的异常处理机制
-
IntelliJ 插件开发注意事项:
- UI 更新必须在 EDT 线程 (ApplicationManager.getApplication().invokeLater)
- 耗时操作应在后台线程执行
- 可以结合使用协程和 IntelliJ 的线程管理 API
-
常用调度器:
Dispatchers.Main- 主线程(UI 线程)Dispatchers.IO- IO 密集型任务Dispatchers.Default- CPU 密集型任务
这些示例展示了 Kotlin 多线程编程在实际项目中的各种应用场景,特别是针对 IntelliJ 插件开发的特点进行了优化。