比如我有两个接收Channel, 但是每一个Channel接收到数据的频率不得而知, 我想分别从中得到数据, 这里就需要使用select.
select<Unit> { channel1.onReceive {} channel2.onReceive {} }如果在配合外围的循环, 就可以做到不断的去接收两个Channel的数据.
再比如有两个发送Channel都可以处理我的需求, 我也不知道这个时候谁是空闲的, 那也可以通过select来解决.
select<Unit> { channel1.onSend(xxx) {} channel2.onSend(xxx) {} }有时候两个Channel是嵌套使用的.
比如一个咖啡店, 他们会不断的收到Oder, 只有两个打咖啡的服务员, 咖啡机也只有两个口, 如果我们对这个咖啡店进行抽象. 将Oder存在于一个Channel里, 服务员接收Order并不断的把咖啡递出来, 这也是一个Channel, 咖啡机会不断接收到服务员需要打咖啡的操作, 也这是一个Channel.
而在这个过程中, 两个服务员会有一个选择, 咖啡机的两个出口也会有一个选择的过程.
如果抽象成我们的Coroutines代码, 或许会是这个样子:
val orderChannel = producer { for (o in orders) send(o) } val waiter1 = producer { for (o in orderChannel) { pullCoffee(o) } } // waiter2 is the same as 1 val coffeePort1 = actor { consumeEach { //pass coffee through channel inside order it.channel.send(Coffee) it.channel.close() } } // coffeePort2 is the same as 2 pullCoffee { select<Coffee> { coffeePort1.onSend(Request(channel)) { //get coffee from coffeePort channel.recevie() } coffeePort2.onSend .... } } while(someCondition) { select<Coffee> { waiter1.onReceiveOrNull { //上菜了 } waiter2.onReceiveOrNull { //上菜了 } } } 补充说明协程作为未来non blocking编程的方向, 需要大家花时间去理解, 花时间去尝试, 在此特别推荐这个咖啡小程序帮助大家学习.
https://medium.com/@jagsaund/kotlin-coroutines-channels-csp-android-db441400965f
以及官方的Overview
https://kotlinlang.org/docs/reference/coroutines-overview.html
还有个CheatSheet可以参考
https://blog.kotlin-academy.com/kotlin-coroutines-cheat-sheet-8cf1e284dc35