Kotlin 并行协程

Kotlin parallel coroutines

从单独的协同程序中保存多个作业实例是否可以接受。假设我想同时 运行 几个协程,其中它们是不相关的并且不能在一个协程中发生,但我希望它们 运行 并行。在 Android 中,我应该保存作业实例,以便我可以在 onDestroy 方法中取消作业。将每项工作分别保存在列表中是否可以接受,或者我是否违反了某种规则。我知道在 RX 中他们有订阅,为什么 Kotlin Coroutines 中没有等效项?

val jobList = arrayListOf<Job>()

fun startJob1() {
    jobList.add(launch {
        //do some work
    })

fun startJob1() {
    jobList.add(launch {
        //do some other unrelated work
    })

override fun onDestroy() {
    super.onDestroy()
    cancelAllActiveJobs(jobList)
}

这种架构对协程有意义吗?

完全可行,也没什么特别的。看看这个一次创建 10 万个工作的简单示例:

val jobs = List(100_000) { // launch a lot of coroutines and list their jobs
        launch {
            delay(1000L)
            print(".")
        }
    }
 jobs.forEach { it.join() } 

为了使作业可取消,它必须自己检查是否已从外部取消,您可以在 activity 状态上循环执行此操作:while (isActive).

这是一个示例,其中有两个作业随后被取消:

fun main(args: Array<String>) = runBlocking {
    val startTime = System.currentTimeMillis()
    val jobs = arrayListOf<Job>()
    jobs += launch {
        var nextPrintTime = startTime
        var i = 0
        while (isActive) { // check if still active
            if (System.currentTimeMillis() >= nextPrintTime) {
                println("Job1: Sleeping ${i++} ...")
                nextPrintTime += 500L
            }
        }
    }

    //another job
    jobs += launch {
        while (isActive) { // check if still active
            if (System.currentTimeMillis() >= 42) {
                println("Job2: Sleeping 42 ...")
                delay(500L)
            }
        }
    }
    delay(1300L) // delay a bit
    println("main: Cancelling the sleeping job!")
    jobs.forEach { it.cancelAndJoin() } // cancels the job and waits for its completion
}

您可以手动保留您启动的 Job 个对象的列表,但您也可以使用开箱即用的父子作业层次结构来管理和保留已启动的列表工作更轻松。

因此,首先,您定义对父作业的引用,而不是作业列表:

val job = Job()

然后,每次启动一个新协程时,您都会将其设为此作业的

fun startJob1() {
    launch(job) { // make it a child
        //do some work
    }
}

fun startJob1() {
    launch(job) { // make it a child
        //do some other unrelated work
    }
}

最后,当您需要销毁对象并取消所有作业时,只需取消父作业即可。

override fun onDestroy() {
    super.onDestroy()
    job.cancel()
}

这种方法的优点是作业列表是自动管理的。可以启动新协程并将其添加到父作业,完成后它们会自动将自己从父作业中移除。

您可以在指南的相应部分阅读更多内容:https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md#cancellation-via-explicit-job