# Coroutines: best way to use fork and join?

**URL:** <https://discuss.kotlinlang.org/t/coroutines-best-way-to-use-fork-and-join/21098>\
**Category:** Libraries\
**Created:** [March 5, 2021, 11:12pm UTC](https://discuss.kotlinlang.org/t/coroutines-best-way-to-use-fork-and-join/21098 "2021-03-05T23:12:45Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![westnordost](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/westnordost/32/6008_2.png) [@westnordost](https://discuss.kotlinlang.org/u/westnordost)\
**Post date:** [March 5, 2021, 11:12pm UTC](https://discuss.kotlinlang.org/t/coroutines-best-way-to-use-fork-and-join/21098/1 "2021-03-05T23:12:45Z")

</div>

With coroutines, there are so many data structures and ways to realize something, I find it easy to lose the overview.

I’d like your opinion what would be the slickest (readability + speed) way to conditionally collect a bunch of computations executed in parallel into an unordered list.

Currently I use something like this, but I wonder if there is something shorter and pure Kotlin:

# launch + ConcurrentLinkedQueue

```
val unorderedResults = ConcurrentLinkedQueue<Int>()
runBlocking {
  for(i in 0..1000) {
    launch {
      if (i % 2 == 0) results.add(i*i)
    }
  }
}

```

I’ve looked at the documentation and found two other ways how to do it:

# async

```
val unorderedResults = runBlocking {
  (0..1000).map { i ->
    async {
      if (i % 2 == 0) i*i else null
    }
  }.awaitAll().filterNotNull()
}

```

Though, not really shorter and there is this extra filter-step. Personally, I also don’t find it better readable. Exchanging the first `map` with `mapNotNull` curiously does not change the type of the list resulting from `awaitAll` to `List<Int>`, it is still `List<Int?>`.

# Channels

```
val unorderedResults = runBlocking {
  val channel = Channel<Int>()
  for (i in 0..1000) {
    launch {
      if (i % 2 == 0) channel.send(i*i)
    }
  }
  val list = ArrayList<Int>()
  channel.consumeEach { list.add(it) }
  list
}

```

From the documentation, I had the impression that this is the intended way to do it because it was mentioned that channels are basically Kotlin’s blocking queues. Not sure if collecting the things sent to the queue into a list could be a one-liner, `map` etc. is deprecated in favour of `Flow`.

---

<div class="post-metadata">

**Author:** ![fvasco](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/fvasco/32/1961_2.png) [@fvasco](https://discuss.kotlinlang.org/u/fvasco)\
**Post date:** [March 6, 2021, 8:40am UTC](https://discuss.kotlinlang.org/t/coroutines-best-way-to-use-fork-and-join/21098/2 "2021-03-06T08:40:07Z")

</div>

I often use the `async` version, but, for your use case, you can consider:

```kotlin
    val unorderedResults = runBlocking(Dispatchers.Default) {
        channelFlow {
            repeat(1000) { i ->
                launch {
                    if (i % 2 == 0) send(i)
                }
            }
        }.toList()
    }

```

Finally, please read carefully the `runBlocking` documentation.

---

<div class="post-metadata">

**Author:** ![westnordost](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/westnordost/32/6008_2.png) [@westnordost](https://discuss.kotlinlang.org/u/westnordost)\
**Post date:** [March 6, 2021, 6:10pm UTC](https://discuss.kotlinlang.org/t/coroutines-best-way-to-use-fork-and-join/21098/3 "2021-03-06T18:10:21Z")

</div>

That looks good, thank you!

---

<div class="post-metadata">

**Author:** ![westnordost](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/westnordost/32/6008_2.png) [@westnordost](https://discuss.kotlinlang.org/u/westnordost)\
**Post date:** [March 6, 2021, 6:36pm UTC](https://discuss.kotlinlang.org/t/coroutines-best-way-to-use-fork-and-join/21098/4 "2021-03-06T18:36:40Z")

</div>

In regards to `runBlocking`, I am not using coroutines comprehensively, but only at some places like these to fan out and merge (or just launch) certain tasks that can run in parallel. So I often have this situation:

```
val result = someClass.doSomeComputationWith(inputSet)

```

…written in non-suspending code and just want particularly some paralellism within that function, i.e. there isn’t some `runBlocking` in the `main` function and the whole codebase is suspending but pretty much the other way round.
