v0ldem0rt
05/08/2020, 5:05 PMoctylFractal
05/08/2020, 5:06 PMwithContext(<http://Dispatchers.IO|Dispatchers.IO>)
and expecting it not to switch?v0ldem0rt
05/08/2020, 5:07 PMoverride val executor = ThreadPoolExecutor(
affinity,
MAX_IO_THREADS,
DEFAULT_TTL_SECONDS_THREAD,
TimeUnit.SECONDS,
SynchronousQueue()
) { runnable ->
Thread(runnable).also {
it.name = "io-pool-${it.id}"
it.isDaemon = true
it.priority = Thread.NORM_PRIORITY
}
}
v0ldem0rt
05/08/2020, 5:07 PMwithContext(executor.asCoroutineDispatcher()){
// ...
}
v0ldem0rt
05/08/2020, 5:08 PMThreadPoolExecutor
I madev0ldem0rt
05/08/2020, 5:08 PMoctylFractal
05/08/2020, 5:09 PMv0ldem0rt
05/08/2020, 5:10 PMv0ldem0rt
05/08/2020, 5:11 PM1.3.72
and coroutines 1.3.5
v0ldem0rt
05/08/2020, 5:14 PMlouiscad
05/08/2020, 5:17 PMasCoroutineDispatcher
for Executor
since <http://Dispatchers.IO|Dispatchers.IO>
exists for my use cases. That said, if you can make a reproducer, simulating the high load you're referring to, I think that'd be a great path towards a fix after reporting on GitHub in kotlinx.coroutines project.v0ldem0rt
05/08/2020, 5:19 PMv0ldem0rt
05/08/2020, 5:20 PM<http://Dispatchers.IO|Dispatchers.IO>
?octylFractal
05/08/2020, 5:20 PM* The number of threads used by this dispatcher is limited by the value of
* "`kotlinx.coroutines.io.parallelism`" ([IO_PARALLELISM_PROPERTY_NAME]) system property.
octylFractal
05/08/2020, 5:23 PMoctylFractal
05/08/2020, 5:24 PMExecutorCoroutineDispatcherImpl
puts tasks on the default executor when the executor rejects the task (due to your SynchronousQueue)octylFractal
05/08/2020, 5:25 PMv0ldem0rt
05/08/2020, 5:29 PMv0ldem0rt
05/08/2020, 5:30 PMobject Application {
@JvmStatic
val IO = ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, SynchronousQueue()) { runnable ->
Thread(runnable).also {
it.name = "io-pool-${it.id}"
it.isDaemon = true
it.priority = Thread.NORM_PRIORITY
}
}
@JvmStatic
fun main(args: Array<String>) {
val dispatcher = IO.asCoroutineDispatcher()
runBlocking(Dispatchers.Default) {
println("Running on ${Thread.currentThread().name}")
(1..10).map {
CoroutineScope(dispatcher).async {
println("Thread using ${Thread.currentThread().name}")
Thread.sleep(1000)
}
}.awaitAll()
}
}
}
octylFractal
05/08/2020, 5:32 PMval executor = ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, SynchronousQueue()) { runnable ->
Thread(runnable).also {
it.name = "io-pool-${it.id}"
it.isDaemon = true
it.priority = Thread.NORM_PRIORITY
}
}
fun main() {
runBlocking(executor.asCoroutineDispatcher()) {
for (i in 1..10) {
launch {
println(Thread.currentThread().name)
Thread.sleep(1000)
}
}
}
}
octylFractal
05/08/2020, 5:32 PMv0ldem0rt
05/08/2020, 5:35 PMExecutorCoroutineDispatcherImpl
that does sov0ldem0rt
05/08/2020, 5:35 PMoctylFractal
05/08/2020, 5:35 PMoverride fun dispatch(context: CoroutineContext, block: Runnable) {
try {
executor.execute(wrapTask(block))
} catch (e: RejectedExecutionException) {
unTrackTask()
DefaultExecutor.enqueue(block)
}
}
v0ldem0rt
05/08/2020, 5:36 PMv0ldem0rt
05/08/2020, 5:37 PMoctylFractal
05/08/2020, 5:38 PMv0ldem0rt
05/08/2020, 5:38 PMoctylFractal
05/08/2020, 5:38 PMv0ldem0rt
05/08/2020, 5:39 PMoctylFractal
05/08/2020, 5:39 PMoctylFractal
05/08/2020, 5:39 PMv0ldem0rt
05/08/2020, 5:39 PMv0ldem0rt
05/08/2020, 5:39 PMLuis Munoz
05/08/2020, 6:05 PMDominaezzz
05/08/2020, 6:06 PM<http://Dispatchers.IO|Dispatchers.IO>
? Use a Semaphore
!Luis Munoz
05/08/2020, 6:06 PMoctylFractal
05/08/2020, 6:09 PMLuis Munoz
05/08/2020, 6:14 PMLuis Munoz
05/08/2020, 6:14 PMLuis Munoz
05/08/2020, 6:14 PMv0ldem0rt
05/08/2020, 7:13 PMv0ldem0rt
05/08/2020, 7:13 PMv0ldem0rt
05/08/2020, 7:14 PMv0ldem0rt
05/08/2020, 7:15 PMwithContext
gives youelizarov
05/08/2020, 10:25 PMv0ldem0rt
05/09/2020, 12:03 AMRejectedExecutionException
v0ldem0rt
05/10/2020, 2:17 AMv0ldem0rt
05/10/2020, 2:17 AMelizarov
05/10/2020, 6:56 AMlaunch {
val file = openFile()
try { .... delay(1000L) ... }
finally { file.close() }
}
What if delay
continuation gets gets rejected when it resumes? We cannot simply abandon this coroutine by throwing RejectedExectionException
somewhere. We also cannot just throw RejectedExectionException
out of delay
because it cannot be throwing it. The right thing to do, though, is to cancel the coroutine using RejectedExectionException
as a cancellation cause.elizarov
05/10/2020, 6:57 AMv0ldem0rt
05/10/2020, 10:15 PMv0ldem0rt
05/10/2020, 10:16 PMAbstractCoroutineContextElement
to disable the fallback behaviour.v0ldem0rt
05/10/2020, 10:17 PMv0ldem0rt
05/10/2020, 10:18 PMDefault
dispatcher.Dominaezzz
05/10/2020, 10:25 PMDominaezzz
05/10/2020, 10:27 PMv0ldem0rt
05/10/2020, 10:57 PMv0ldem0rt
05/10/2020, 10:58 PM