kotlin 中 多线程

31 阅读1分钟

一些 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("任务已完成")
    }
}

关键要点总结

  1. 协程 vs 传统线程

    • 协程更轻量级,启动速度快
    • 协程有更好的结构化并发支持
    • 协程提供更简洁的异常处理机制
  2. IntelliJ 插件开发注意事项

  3. 常用调度器

    • Dispatchers.Main - 主线程(UI 线程)
    • Dispatchers.IO - IO 密集型任务
    • Dispatchers.Default - CPU 密集型任务

这些示例展示了 Kotlin 多线程编程在实际项目中的各种应用场景,特别是针对 IntelliJ 插件开发的特点进行了优化。