【问题标题】:Running blocking CPU bound tasks on Kotlin coroutines在 Kotlin 协程上运行阻塞 CPU 绑定任务
【发布时间】:2020-01-04 08:56:38
【问题描述】:

我一直在试验 Kotlin 并在 kotlin 协程上运行阻塞 CPU 任务。当事情被阻塞时,例如大型 cpu 密集型计算,我们实际上并没有暂停,而是我们需要在不同的线程上启动事情并让它们并行运行。

我设法使以下代码在 async + Default 调度程序中按预期工作,但想知道它是否可以与 withContext 一起工作,但事实并非如此。

fun cpuBlockingTasks() = runBlocking {
    val time = measureTimeMillis {
        val t1 = cpuTask(id = 1, blockTime = 500)
        val t2 = cpuTask(id = 2, blockTime = 2000)
        println("The answer is ${t1 + t2}")
    }
    println("Time taken: $time")
}
suspend fun cpuTask(id: Int, blockTime: Long): Int = withContext(Dispatchers.Default) {
    println("work $id start ${getThreadName()}")
    val res = doSomeCpuIntensiveTask(blockTime)
    println("work $id end ${getThreadName()}")
    res
}
fun doSomeCpuIntensiveTask(time: Long): Int {
    Thread.sleep(time) // to mimick actual thread blocking / cpu work
    return 1
}

此代码在 >2500 毫秒内完成并按顺序在同一线程上运行。我期待它启动线程中的第一个协程,立即返回调用者并在另一个线程上启动第二个协程,但没有像那样工作。任何人都知道为什么会这样以及如何在不在调用者函数中启动 async 协程的情况下修复它?

这是输出

work 1 start ForkJoinPool.commonPool-worker-5 @coroutine#1
work 1 end ForkJoinPool.commonPool-worker-5 @coroutine#1
work 2 start ForkJoinPool.commonPool-worker-5 @coroutine#1
work 2 end ForkJoinPool.commonPool-worker-5 @coroutine#1
The answer is 2
Time taken: 2523

【问题讨论】:

    标签: multithreading kotlin parallel-processing blocking coroutine


    【解决方案1】:

    您没有在cpuTask 1cpuTask 2 中创建新的协程。您只是在切换上下文。可以通过async轻松修复:

    fun cpuBlockingTasks() = runBlocking {
        val time = measureTimeMillis {
            val t1 = async { cpuTask(id = 1, blockTime = 500) }
            val t2 = async { cpuTask(id = 2, blockTime = 2000) }
            println("The answer is ${t1.await() + t2.await()}")
        }
        println("Time taken: $time") // Time taken: 2026
    }
    

    【讨论】:

    • 好的,我明白了。所以 withContext 并没有真正创建一个新的协程,而是继续在不同的线程上运行同一个协程。是否有可能避免使用 async/await 并获得相同的行为?
    • 使用协程,它可以通过几种不同的方式完成。例如,使用launch/join 或频道。但在我看来,async 是最适合这种情况的一个
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-21
    • 2020-11-04
    • 2019-12-26
    • 2022-12-12
    相关资源
    最近更新 更多