如何在Kotlin中实现基于Job ID的任务启停API?
Kotlin 任务启动与取消API实现方案
核心实现思路
要支持多任务的启动与ID关联取消,核心是用线程安全的映射容器管理任务ID和对应协程Job的关联关系,同时保证任务ID的唯一性。具体逻辑:
- 用
ConcurrentHashMap存储任务ID与Job的映射,应对多线程下的并发访问 - 生成唯一任务ID(推荐用UUID,无需处理自增的线程安全问题)
- 启动接口:启动协程任务,绑定ID后返回标识
- 取消接口:根据ID查找对应任务,执行取消并等待任务终止
完整代码实现
import kotlinx.coroutines.* import java.util.* import java.util.concurrent.ConcurrentHashMap // 全局任务管理器单例 object TaskManager { // 线程安全的任务映射:任务ID -> 对应的协程Job private val jobMap = ConcurrentHashMap<String, Job>() /** * 启动任务并返回唯一任务ID * @param task 要执行的协程任务 * @return 任务唯一标识ID */ fun startJob(task: suspend CoroutineScope.() -> Unit): String { val jobId = UUID.randomUUID().toString() // 启动协程任务,可根据需求调整Dispatcher val job = CoroutineScope(Dispatchers.Default).launch(block = task) jobMap[jobId] = job // 任务完成后自动从映射中移除,避免内存泄漏 job.invokeOnCompletion { jobMap.remove(jobId) } return jobId } /** * 根据任务ID取消对应任务 * @param jobId 任务唯一标识ID * @return 是否成功取消(ID存在且任务未完成则返回true) */ suspend fun cancelJob(jobId: String): Boolean { val job = jobMap[jobId] ?: return false if (job.isCompleted || job.isCancelled) { jobMap.remove(jobId) return false } job.cancel() job.join() // 等待任务完全终止 jobMap.remove(jobId) return true } } // 演示使用 fun main() = runBlocking { // 启动第一个任务 val jobId1 = TaskManager.startJob { for (i in 0..1000) { delay(50) if (isActive) { // 检查任务活跃状态,确保能响应取消 println("任务1: $i..") } } println("任务1: 执行完成") } // 启动第二个任务 val jobId2 = TaskManager.startJob { for (i in 0..1000) { delay(50) if (isActive) { println("任务2: $i..") } } println("任务2: 执行完成") } // 等待1秒后取消第一个任务 delay(1000) println("开始取消任务1,ID: $jobId1") val cancelResult1 = TaskManager.cancelJob(jobId1) println("任务1取消结果: $cancelResult1") // 等待第二个任务执行完成 delay(5000) println("程序结束") }
关键细节说明
- 线程安全:
ConcurrentHashMap确保多线程环境下启动/取消任务时的映射操作不会出现并发问题 - 内存泄漏防护:通过
job.invokeOnCompletion在任务完成(正常结束或被取消)后自动从映射中移除条目 - 取消有效性:协程任务内部需要通过
isActive检查或调用挂起函数(如delay)才能响应取消;如果是纯CPU密集型任务,需手动添加yield()或isActive判断 - 状态反馈:
cancelJob方法返回布尔值,方便调用方判断取消操作是否成功(比如ID不存在、任务已完成时返回false)
内容的提问来源于stack exchange,提问作者user20094830
相关产品推荐
相关产品推荐

