我一直在试验 Kotlin 并在 kotlin 协程上运行阻塞 CPU 任务。当事情发生阻塞时,例如大型 cpu 密集型计算,我们实际上并没有暂停,而是我们需要在不同的线程上启动事情并让它们并行运行。
我设法使以下代码与 async + Default dispatcher 一起按预期工作,但想知道它是否可以与 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
最佳答案
您没有在 cpuTask 1
和 cpuTask 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
}
关于multithreading - 在 Kotlin 协程上运行阻塞的 CPU 绑定(bind)任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57737998/