You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin中实现基于Job ID的任务启停API?

Kotlin 任务启动与取消API实现方案

核心实现思路

要支持多任务的启动与ID关联取消,核心是用线程安全的映射容器管理任务ID和对应协程Job的关联关系,同时保证任务ID的唯一性。具体逻辑:

  1. 用ConcurrentHashMap存储任务ID与Job的映射,应对多线程下的并发访问
  2. 生成唯一任务ID(推荐用UUID,无需处理自增的线程安全问题)
  3. 启动接口:启动协程任务,绑定ID后返回标识
  4. 取消接口:根据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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 04:02:20