使用线程池作为调度程序时,delay() 会阻塞其协程吗?
delay() block its coroutine when using thread pool as the dispatcher?
玩转Kotlin协程,我的玩具代码结果一头雾水:
import kotlinx.coroutines.*
import java.util.concurrent.Executors
suspend fun task(sleepTime: Long) {
println("start task in Thread ${Thread.currentThread()}")
delay(sleepTime)
//yield()
println("end task with context in Thread ${Thread.currentThread()}")
}
println("start")
runBlocking {
val handler = CoroutineExceptionHandler() { context, ex ->
println("Caught: $context | ${ex.message}")
}
Executors.newFixedThreadPool(2)
.asCoroutineDispatcher().use { dispatcher ->
launch(dispatcher + handler) { task(100) }
launch(Dispatchers.IO + handler) { task(1000) }
println("called tasks ${Thread.currentThread()}")
}
}
println("done")
输出:
start
start task in Thread Thread[pool-1-thread-1 @coroutine#2,5,main]
called tasks Thread[main @coroutine#1,5,main]
start task in Thread Thread[DefaultDispatcher-worker-2 @coroutine#3,5,main]
end task with context in Thread Thread[DefaultDispatcher-worker-2 @coroutine#3,5,main]
done
我的问题是为什么协程#1 不继续?如果我将 delay() 更改为 yield(),它会起作用:
start
start task in Thread Thread[pool-1-thread-1 @coroutine#2,5,main]
end task with context in Thread Thread[pool-1-thread-2 @coroutine#2,5,main]
called tasks Thread[main @coroutine#1,5,main]
start task in Thread Thread[DefaultDispatcher-worker-1 @coroutine#3,5,main]
end task with context in Thread Thread[DefaultDispatcher-worker-1 @coroutine#3,5,main]
done
Closeable.use
执行其中的代码,然后关闭 Closable,在本例中是您的调度程序。由于启动的协程是 运行 异步的,use
不会等待它们完成,而是立即关闭调度程序,从而取消您的协程。有可能 yield()
发生得如此之快,以至于他们有时间在被取消之前完成。
如果您将 use
块移动到 runBlocking
块之外,然后它会等待它们完成。
fun main() {
println("start")
Executors.newFixedThreadPool(2)
.asCoroutineDispatcher().use { dispatcher ->
runBlocking {
val handler = CoroutineExceptionHandler() { context, ex ->
println("Caught: $context | ${ex.message}")
}
launch(dispatcher + handler) { task(100) }
launch(Dispatchers.IO + handler) { task(1000) }
println("called tasks ${Thread.currentThread()}")
}
}
println("done")
}
玩转Kotlin协程,我的玩具代码结果一头雾水:
import kotlinx.coroutines.*
import java.util.concurrent.Executors
suspend fun task(sleepTime: Long) {
println("start task in Thread ${Thread.currentThread()}")
delay(sleepTime)
//yield()
println("end task with context in Thread ${Thread.currentThread()}")
}
println("start")
runBlocking {
val handler = CoroutineExceptionHandler() { context, ex ->
println("Caught: $context | ${ex.message}")
}
Executors.newFixedThreadPool(2)
.asCoroutineDispatcher().use { dispatcher ->
launch(dispatcher + handler) { task(100) }
launch(Dispatchers.IO + handler) { task(1000) }
println("called tasks ${Thread.currentThread()}")
}
}
println("done")
输出:
start
start task in Thread Thread[pool-1-thread-1 @coroutine#2,5,main]
called tasks Thread[main @coroutine#1,5,main]
start task in Thread Thread[DefaultDispatcher-worker-2 @coroutine#3,5,main]
end task with context in Thread Thread[DefaultDispatcher-worker-2 @coroutine#3,5,main]
done
我的问题是为什么协程#1 不继续?如果我将 delay() 更改为 yield(),它会起作用:
start
start task in Thread Thread[pool-1-thread-1 @coroutine#2,5,main]
end task with context in Thread Thread[pool-1-thread-2 @coroutine#2,5,main]
called tasks Thread[main @coroutine#1,5,main]
start task in Thread Thread[DefaultDispatcher-worker-1 @coroutine#3,5,main]
end task with context in Thread Thread[DefaultDispatcher-worker-1 @coroutine#3,5,main]
done
Closeable.use
执行其中的代码,然后关闭 Closable,在本例中是您的调度程序。由于启动的协程是 运行 异步的,use
不会等待它们完成,而是立即关闭调度程序,从而取消您的协程。有可能 yield()
发生得如此之快,以至于他们有时间在被取消之前完成。
如果您将 use
块移动到 runBlocking
块之外,然后它会等待它们完成。
fun main() {
println("start")
Executors.newFixedThreadPool(2)
.asCoroutineDispatcher().use { dispatcher ->
runBlocking {
val handler = CoroutineExceptionHandler() { context, ex ->
println("Caught: $context | ${ex.message}")
}
launch(dispatcher + handler) { task(100) }
launch(Dispatchers.IO + handler) { task(1000) }
println("called tasks ${Thread.currentThread()}")
}
}
println("done")
}