data-decode
data-decode

Reputation: 103

Async Wait Efficient Execution

I need to iterate 100's of ids in parallel and collect the result in list. I am trying to do it in following way

val context = newFixedThreadPoolContext(5, "custom pool")
val list = mutableListOf<String>()
ids.map { 
  val result:Deferred<String> =  async(context) {
    getResult(it)
  }
//list.add(result.await()
}.mapNotNull(result -> list.add(result.await())

I am getting error at

mapNotNull(result -> list.add(result.await())

as await method is not available. Why await is not applicable at this place? Instead commented line //list.add(result.await() is working fine.

What is the best way to run this block in parallel using coroutine with custom thread pool?

Upvotes: 3

Views: 341

Answers (1)

broot
broot

Reputation: 28332

Generally, you go in the right direction: you need to create a list of Deferred and then await() on them.

If this is exactly the code you are using then you did not return anything from your first map { } block, so you don't get a List<Deferred> as you expect, but List<Unit> (list of nothing). Just remove val result:Deferred<String> = - this way you won't assign result to a variable, but return it from the lambda. Also, there are two syntactic errors in the last line: you used () instead of {} and there is a missing closing parenthesis.

After these changes I believe your code will work, but still, it is pretty weird. You seem to mix two distinct approaches to transform a collection into another. One is using higher-order functions like map() and another is using a loop and adding to a list. You use both of them at the same time. I think the following code should do exactly what you need (thanks @Joffrey for improving it):

val list = ids.map { 
    async(context) {
        getResult(it)
    }
}.awaitAll().filterNotNull()

Upvotes: 3

Related Questions