val context = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()).asCoroutineDispatcher() fun main() { val foo = Foo() val foo2 = Foo() thread { while (true) foo.spawn() } thread { while (true) foo2.spawn() } Thread.sleep(5000) foo2.close() } class Foo { private val instanceScope = CoroutineScope(context) private var bar = Bar(instanceScope) fun spawn() { runBlocking { val streamer = bar.streamer() for (x in streamer) { println("${Thread.currentThread().name} got a $x") } } } fun close() = instanceScope.cancel() } class Bar(scope: CoroutineScope) : CoroutineScope by scope { var num = Random.nextInt(10000) var invocations = 0 fun streamer() = produce { invocations++ repeat(5) { delay(500) send("$invocations-${num++}") } } }