Gerardo Epitacio
08/08/2023, 6:13 AM_runBlocking_(<http://Dispatchers.IO|Dispatchers.IO>) , not totally sure if this is the way to go, seem like not.
Adding a little more explanation:
1. Kotlin creates a couple( 400 ) coroutines with async coroutines builder, which executes some operations in async using async coroutine builder
2. The created coroutine call some complex Java code that requires to do some database operations, that’s why I need to call a regular Kotlin method and that regular Kotlin method calls the room function with a valid coroutine scope create with runBlocking.
3. Doing a Thread Dump visualization I got something like the shared picture.
Note: All flow of my program works just fine if I lunch around 50 coroutines (I did a test with that amount), but seems like more than one hundred causes the hang.xoangon
08/08/2023, 6:21 AMCoroutineScope that you could be generating for that case.
As the Kotlin function is not suspend, you shouldn’t have any problem on calling it from JavaGerardo Epitacio
08/08/2023, 6:48 AMGerardo Epitacio
08/08/2023, 6:51 AM// creates around 400 coroutines with async
override suspend fun executeExpressions() {
val expressionSize = this.expressions.size
val expressionsToExecute: List<FxlExpression> = this.expressions.values.toList()
val result: List<Deferred<String>> = expressionsToExecute.mapIndexed { index, expressionObject ->
async {
println("Expression ($index/$expressionSize) ${expressionObject.key} started")
// calls Java code as part of the operation logic.
val result: String? = executeExpression(expressionObject.key, expressionObject.value)
println("Expression ($index/$expressionSize) ${expressionObject.key} finished")
"Expression ($index/$expressionSize) ${expressionObject.key} result $result"
}
}
val result = result.awaitAll()
}Gerardo Epitacio
08/08/2023, 6:53 AM// called from Java code that calls a suspend function
@Synchronized
@Expe`rimentalCoroutinesApi`
override fun executeBehavior(evaluator: Evaluator, behaviorKey: String): Boolean {
return _runBlocking_(this.dispatcher) *{*
// suspend Room database methods.
}
}xoangon
08/08/2023, 6:59 AMxoangon
08/08/2023, 7:02 AMrunBlocking(<http://Dispatchers.IO|Dispatchers.IO>) is the right choice. If this latter is your case, you can still take a look at the project Loom virtual threads in JavaGerardo Epitacio
08/08/2023, 7:02 AMGerardo Epitacio
08/08/2023, 7:04 AMxoangon
08/08/2023, 7:10 AMCoroutineScope context comes from that allows you to call the async function?
Are you creating your own implementation of CoroutineScope extending from the interface?Gerardo Epitacio
08/08/2023, 7:27 AMGerardo Epitacio
08/08/2023, 7:40 AMGerardo Epitacio
08/08/2023, 7:45 AMxoangon
08/08/2023, 7:46 AMCoroutineScope for a case like this. Using coroutineScope as in this last example is the correct approach.
That is an improvement but not the root cause of your problem. You should call the executeExpression suspend function in a CoroutineScope instance instead of inside the runBlocking scope. This latter one will be blocking threads and you may not be able to launch 400 blocking coroutines. You could instead use GlobalScope.launch { } or create your own CoroutineScope instance using the CoroutineScope() factory functionGerardo Epitacio
08/08/2023, 7:46 AMxoangon
08/08/2023, 7:46 AMGerardo Epitacio
08/08/2023, 7:48 AMprivate val supervisor: CompletableJob = _SupervisorJob_()
private val coroutineScope = _CoroutineScope_(supervisor)