Kotlin 协程:在单线程中一次一个协程
Kotlin Coroutines: one single coroutine at a time in single thread
考虑下面的代码,我正在尝试使用 Executors.newFixedThreadPool(1).asCoroutineDispatcher()
创建单线程调度程序;我希望 launch(singleThread){...}
中的代码按顺序执行
预期结果应该如下所示,因为 async-block#2 reach/acquire singleThread first
async block #2
async block #1
single thread block #2
single thread block #1
The answer is 3
但实际结果是
async block #2
async block #1
single thread block #1
single thread block #2
The answer is 3
single-thread-block-#2 和 single-thread-block-#1 似乎 运行 并行,singleThread 在这里没有区别
</p>
<pre><code>import java.util.concurrent.Executors
import kotlinx.coroutines.*
import kotlin.system.*
val singleThread = Executors.newFixedThreadPool(1).asCoroutineDispatcher()
fun main() = runBlocking<Unit> {
val time = measureTimeMillis {
val one = async { // async block #1
delay(200)
println("async block #1")
launch (singleThread) {
delay(500)
println("single thread block #1")
}
2
}
val two = async { // async block #2
delay(100)
println("async block #2")
launch (singleThread) {
delay(1500)
println("single thread block #2")
}
1
}
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
}
注意 delay()
是代码中的 suspend
函数。它是通过协程挂起实现的。这意味着代码的执行在您调用 delay
的那一刻暂停,只有在超时后才恢复。线程(例如,您通过 async(singleThread) {..}
使用的线程不忙,等待时间结束。
总体情况是这样的
- ...
- "async block #2" 印刷
- 任务 2 运行宁
singleThread
- 任务 2 暂停
delay(1500)
,singleThread
空闲
- 任务 1 在
singleThread
开始
- 任务 1 暂停
delay(500)
,singleThread
空闲
- 那时我们有延迟队列:
- 恢复任务 1
delay(500)
- 恢复任务 2
delay(1500)
- 一段时间后
resume(500)
将任务 1 的第二部分安排到 singleThread
中的 运行
- 一段时间后
resume(1500)
将任务 2 的第二部分安排到 singleThread
中的 运行
除了@EugenePetrenko 的回答之外,还有一个新方法 CoroutineDispatcher.limitedParallelism(numberOfParallelism)
,您可以使用它来保证并行性限制 - 在此调度程序中最多可以并发执行 1 个协程。它看起来像:
val singleThread = Dispatchers.IO.limitedParallelism(1)
someCoroutineScope.launch (singleThread) {
...
}
函数 limitedParallelism
从 kotlinx.coroutines
库的 1.6.0 版本开始可用。
考虑下面的代码,我正在尝试使用 Executors.newFixedThreadPool(1).asCoroutineDispatcher()
创建单线程调度程序;我希望 launch(singleThread){...}
中的代码按顺序执行
预期结果应该如下所示,因为 async-block#2 reach/acquire singleThread first
async block #2
async block #1
single thread block #2
single thread block #1
The answer is 3
但实际结果是
async block #2
async block #1
single thread block #1
single thread block #2
The answer is 3
single-thread-block-#2 和 single-thread-block-#1 似乎 运行 并行,singleThread 在这里没有区别
</p>
<pre><code>import java.util.concurrent.Executors
import kotlinx.coroutines.*
import kotlin.system.*
val singleThread = Executors.newFixedThreadPool(1).asCoroutineDispatcher()
fun main() = runBlocking<Unit> {
val time = measureTimeMillis {
val one = async { // async block #1
delay(200)
println("async block #1")
launch (singleThread) {
delay(500)
println("single thread block #1")
}
2
}
val two = async { // async block #2
delay(100)
println("async block #2")
launch (singleThread) {
delay(1500)
println("single thread block #2")
}
1
}
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
}
注意 delay()
是代码中的 suspend
函数。它是通过协程挂起实现的。这意味着代码的执行在您调用 delay
的那一刻暂停,只有在超时后才恢复。线程(例如,您通过 async(singleThread) {..}
使用的线程不忙,等待时间结束。
总体情况是这样的
- ...
- "async block #2" 印刷
- 任务 2 运行宁
singleThread
- 任务 2 暂停
delay(1500)
,singleThread
空闲 - 任务 1 在
singleThread
开始
- 任务 1 暂停
delay(500)
,singleThread
空闲 - 那时我们有延迟队列:
- 恢复任务 1
delay(500)
- 恢复任务 2
delay(1500)
- 恢复任务 1
- 一段时间后
resume(500)
将任务 1 的第二部分安排到singleThread
中的 运行
- 一段时间后
resume(1500)
将任务 2 的第二部分安排到singleThread
中的 运行
除了@EugenePetrenko 的回答之外,还有一个新方法 CoroutineDispatcher.limitedParallelism(numberOfParallelism)
,您可以使用它来保证并行性限制 - 在此调度程序中最多可以并发执行 1 个协程。它看起来像:
val singleThread = Dispatchers.IO.limitedParallelism(1)
someCoroutineScope.launch (singleThread) {
...
}
函数 limitedParallelism
从 kotlinx.coroutines
库的 1.6.0 版本开始可用。