Issue
Play with Kotlin coroutine, I am confused by the results of my toy code:
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")
output:
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
My question is why coroutine#1 does not continue? If I change delay() to yield(), it worked:
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
Solution
Closeable.use
executes the code inside it and then closes the Closable, in this case your dispatcher. Since launched coroutines are run asynchronously, use
doesn't wait for them to finish, and shuts down the dispatcher right away, thereby cancelling your coroutines. It's possible yield()
happens so quickly that they have time to finish before getting cancelled.
If you move your use
block outside the runBlocking
block, then it waits for them to finish.
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")
}
Answered By - Tenfour04
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.