Upgrade to Pro — share decks privately, control downloads, hide ads and more …

@Experimental Kotlin coroutines

@Experimental Kotlin coroutines

Overview of the experimental and obsolete features of the Kotlin coroutines library version 1.3.0-M1.

Iveta Jurcikova

June 18, 2019
Tweet

More Decks by Iveta Jurcikova

Other Decks in Programming

Transcript

  1. 4

  2. 6

  3. 7

  4. 8

  5. 9

  6. 10

  7. 12

  8. 13

  9. 14

  10. 15

  11. 16

  12. 17

  13. 18

  14. 19

  15. 20

  16. 21

  17. 22

  18. 23

  19. 24

  20. 25

  21. 26

  22. 30

  23. 31

  24. 32

  25. 33

  26. 34

  27. 35

  28. 36

  29. 37

  30. 38

  31. 39

  32. 42 SINGLE THREAD HAMBURGER STAND fun main() { val time

    = measureTimeMillis { runBlocking { launch(CoroutineName("Ivet")) { makeHamburger(orders()) }} }} }} log("Order processed in $time milliseconds") }} private suspend fun makeHamburger(orders: List<Order>) = orders.forEach { order -> log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = fryMeat(order.id) val bun = heatBun(order.id) val hamburger = prepareHamburger(vegetable, meat, bun) log("Serve $hamburger") }}
  33. 43 SINGLE THREAD HAMBURGER STAND fun main() { val time

    = measureTimeMillis { runBlocking { launch(CoroutineName("Ivet")) { makeHamburger(orders()) }} }} }} log("Order processed in $time milliseconds") }} private suspend fun makeHamburger(orders: List<Order>) = orders.forEach { order -> log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = fryMeat(order.id) val bun = heatBun(order.id) val hamburger = prepareHamburger(vegetable, meat, bun) log("Serve $hamburger") }}
  34. 44 SINGLE THREAD HAMBURGER STAND fun main() { val time

    = measureTimeMillis { runBlocking { launch(CoroutineName("Ivet")) { makeHamburger(orders()) }} }} }} log("Order processed in $time milliseconds") }} private suspend fun makeHamburger(orders: List<Order>) = orders.forEach { order -> log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = fryMeat(order.id) val bun = heatBun(order.id) val hamburger = prepareHamburger(vegetable, meat, bun) log("Serve $hamburger") }}
  35. 47 fun main() {{ val time = measureTimeMillis {{ runBlocking

    {{ launch(CoroutineName("Ivet")) {{ makeHamburger(orders())) }} }} }} log("Order processed in $time milliseconds”)) }} private suspend fun makeHamburger(orders: List<Order>) = orders.forEach { order -> log("Processing ${order.id}. order”)) val vegetable = cutVegetable(order.id) val meat = fryMeat(order.id) val bun = heatBun(order.id) val hamburger = prepareHamburger(vegetable, meat, bun)) log("Serve $hamburger”)) }} CONCURRENT HAMBURGER STAND
  36. fun main() {{ val time = measureTimeMillis {{ runBlocking {{

    launch(CoroutineName("Ivet")) {{ makeHamburger(orders())) }} }} }} log("Order processed in $time milliseconds”)) }} private suspend fun makeHamburger(orders: List<Order>) = orders.forEach { order -> log("Processing ${order.id}. order”)) val vegetable = cutVegetable(order.id) val meat = fryMeat(order.id) val bun = heatBun(order.id) val hamburger = prepareHamburger(vegetable, meat, bun)) log("Serve $hamburger”)) }} 48 CONCURRENT HAMBURGER STAND
  37. fun main() {{ val time = measureTimeMillis {{ runBlocking {{

    launch(CoroutineName("Ivet")) {{ makeHamburger(orders())) }} }} }} log("Order processed in $time milliseconds”)) }} private suspend fun makeHamburger(orders: List<Order>) = coroutineScope {{ orders.forEach { order -> log("Processing ${order.id}. order”)) val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger(vegetable, meat.await(), bun.await())) log("Serve $hamburger”)) }} }} 49 CONCURRENT HAMBURGER STAND
  38. fun main() {{ val time = measureTimeMillis {{ runBlocking {{

    launch(CoroutineName("Ivet")) {{ makeHamburger(orders())) }} }} }} log("Order processed in $time milliseconds”)) }} private suspend fun makeHamburger(orders: List<Order>) = coroutineScope {{ orders.forEach { order -> log("Processing ${order.id}. order”)) val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger(vegetable, meat.await(), bun.await())) log("Serve $hamburger”)) }} }} 50 CONCURRENT HAMBURGER STAND
  39. HIGH SEASON CONCURRENT HAMBURGER STAND Employees: • Cook • Ivet

    • Dominika • Cashier • Lenka 53 Appliances: • 2 knifes • 2 deep fryers • 2 microwaves
  40. • A transfer medium for a stream of values •

    Similar to BlockingQueue • Operations: • Suspending send() • Suspending receive() • Roles: • SenderChannel • x ReceiveChannel CHANNEL 61
  41. RECEIVE CHANNEL 64 fun main() { val time = measureTimeMillis

    { runBlocking { val ordersChannel = Channel<Order>() launch(CoroutineName("People")) { orders(3).forEach { order -> ordersChannel.send(order) }} ordersChannel.close() }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }} private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> ) = coroutineScope { for (order in ordersChannel) { log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }}
  42. RECEIVE CHANNEL 65 fun main() { val time = measureTimeMillis

    { runBlocking { val ordersChannel = Channel<Order>() launch(CoroutineName("People")) { orders(3).forEach { order -> ordersChannel.send(order) }} ordersChannel.close() }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }} private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> ) = coroutineScope { for (order in ordersChannel) { log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }}
  43. RECEIVE CHANNEL 66 fun main() { val time = measureTimeMillis

    { runBlocking { val ordersChannel = Channel<Order>() launch(CoroutineName("People")) { orders(3).forEach { order -> ordersChannel.send(order) }} ordersChannel.close() }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }} private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> ) = coroutineScope { for (order in ordersChannel) { log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }}
  44. fun main() { val time = measureTimeMillis { runBlocking {

    val ordersChannel = Channel<Order>() launch(CoroutineName("People")) { orders(3).forEach { order -> ordersChannel.send(order) }} ordersChannel.close() }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }} RECEIVE CHANNEL 67 private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> ) = coroutineScope { for (order in ordersChannel) { log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }}
  45. fun main() { val time = measureTimeMillis { runBlocking {

    val ordersChannel = Channel<Order>() launch(CoroutineName("People")) { orders(3).forEach { order -> ordersChannel.send(order) }} ordersChannel.close() }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }} RECEIVE CHANNEL 68 private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> ) = coroutineScope { for (order in ordersChannel) { log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }}
  46. fun main() { val time = measureTimeMillis { runBlocking {

    val ordersChannel = Channel<Order>() launch(CoroutineName("People")) { orders(3).forEach { order -> ordersChannel.send(order) }} ordersChannel.close() }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }} RECEIVE CHANNEL 69 private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> ) = coroutineScope { for (order in ordersChannel) { log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }}
  47. RECEIVE CHANNEL 70 private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> )

    = coroutineScope { for (order in ordersChannel) { log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }} fun main() { val time = measureTimeMillis { runBlocking { val ordersChannel = Channel<Order>() launch(CoroutineName("People")) { orders(3).forEach { order -> ordersChannel.send(order) }} ordersChannel.close() }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }}
  48. RECEIVE CHANNEL 71 private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> )

    = coroutineScope { for (order in ordersChannel) { log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }} fun main() { val time = measureTimeMillis { runBlocking { val ordersChannel = Channel<Order>() launch(CoroutineName("People")) { orders(3).forEach { order -> ordersChannel.send(order) }} ordersChannel.close() }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }}
  49. RECEIVE CHANNEL 72 private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> )

    = coroutineScope { for (order in ordersChannel) { log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }} fun main() { val time = measureTimeMillis { runBlocking { val ordersChannel = Channel<Order>() launch(CoroutineName("People")) { orders(3).forEach { order -> ordersChannel.send(order) }} ordersChannel.close() }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }}
  50. fun main() { val time = measureTimeMillis { runBlocking {

    val ordersChannel = Channel<Order>() launch(CoroutineName("People")) { orders(3).forEach { order -> ordersChannel.send(order) }} ordersChannel.close() }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }} RECEIVE CHANNEL 73 private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> ) = coroutineScope { for (order in ordersChannel) { log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }}
  51. fun main() { val time = measureTimeMillis { runBlocking {

    val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) }} }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }} RECEIVE CHANNEL 74 private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> ) = coroutineScope { for (order in ordersChannel) { log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }}
  52. fun main() { val time = measureTimeMillis { runBlocking {

    val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) }} }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }} RECEIVE CHANNEL 74 private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> ) = coroutineScope { for (order in ordersChannel) { log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }}
  53. fun main() { val time = measureTimeMillis { runBlocking {

    val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) }} }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }} RECEIVE CHANNEL 75 private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> ) = coroutineScope { for (order in ordersChannel) { log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }}
  54. private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> ) = coroutineScope {

    ordersChannel.consumeEach { order -> log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }} RECEIVE CHANNEL 76 fun main() { val time = measureTimeMillis { runBlocking { val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) }} }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }}
  55. private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> ) = coroutineScope {

    ordersChannel.consumeEach { order -> log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }} RECEIVE CHANNEL 76 fun main() { val time = measureTimeMillis { runBlocking { val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) }} }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }}
  56. RECEIVE CHANNEL 77 private suspend fun makeHamburger( ordersChannel: ReceiveChannel<Order> )

    = coroutineScope { for (order in ordersChannel) { log("Processing ${order.id}. order") val vegetable = cutVegetable(order.id) val meat = async { fryMeat(order.id) } val bun = async { heatBun(order.id) } val hamburger = prepareHamburger( vegetable, meat.await(), bun.await() )) log("Serve $hamburger") }} }} fun main() { val time = measureTimeMillis { runBlocking { val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) }} }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) }} launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) }} }} }} log("Order processed in $time milliseconds") }}
  57. 82

  58. 83

  59. 84

  60. 85

  61. 86

  62. 87

  63. 88 fun main() { val time = measureTimeMillis { runBlocking

    { val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) }} }} launch(CoroutineName("Ivet")) { makeHamburger(ordersChannel) } launch(CoroutineName("Dominika")) { makeHamburger(ordersChannel) } } } log("Order processed in $time milliseconds") }}
  64. 89 fun main() { val time = measureTimeMillis { runBlocking

    { val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) }} }} ... }} fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while (isActive) { log("Tapping $count. beer") delay(200) send(Beer(count++)) }} }}
  65. 90 fun main() { val time = measureTimeMillis { runBlocking

    { val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) }} }} ... }} fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while (isActive) { log("Tapping $count. beer”) delay(200) send(Beer(count++)) }} }}
  66. 91 fun main() { val time = measureTimeMillis { runBlocking

    { val beersChannel = beersChannel() val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) }} }} ... }} fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while (isActive) { log("Tapping $count. beer”) delay(200) send(Beer(count++)) }} }}
  67. 92 fun main() { val time = measureTimeMillis { runBlocking

    { val beersChannel = beersChannel() val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Received ${beersChannel.receive()}") }} }} ... }} fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while (isActive) { log("Tapping $count. beer”) delay(200) send(Beer(count++)) }} }}
  68. 93 fun main() { val time = measureTimeMillis { runBlocking

    { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while (isActive) { log("Tapping $count. beer”) delay(200) send(Beer(count++)) }} }}
  69. 94 fun main() { val time = measureTimeMillis { runBlocking

    { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while (isActive) { log("Tapping $count. beer”) delay(200) send(Beer(count++)) }} }}
  70. 95 fun main() { val time = measureTimeMillis { runBlocking

    { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while (isActive) { log("Tapping $count. beer”) delay(200) send(Beer(count++)) }} }}
  71. 97 fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1

    while (isActive) { log("Tapping $count. beer") delay(200) send(Beer(count++)) }} }} fun main() { val time = measureTimeMillis { runBlocking { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }}
  72. fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while

    (isActive) { log("Tapping $count. beer") delay(200) send(Beer(count++)) }} }} fun main() { val time = measureTimeMillis { runBlocking { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} 98
  73. fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while

    (isActive) { log("Tapping $count. beer") delay(200) send(Beer(count++)) }} }} fun main() { val time = measureTimeMillis { runBlocking { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} 99
  74. fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while

    (isActive) { log("Tapping $count. beer") delay(200) send(Beer(count++)) }} }} fun main() { val time = measureTimeMillis { runBlocking { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} 100
  75. fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while

    (isActive) { log("Tapping $count. beer") delay(200) send(Beer(count++)) }} }} fun main() { val time = measureTimeMillis { runBlocking { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} 101
  76. fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while

    (isActive) { log("Tapping $count. beer") delay(200) send(Beer(count++)) }} }} fun main() { val time = measureTimeMillis { runBlocking { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} 102
  77. fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while

    (isActive) { log("Tapping $count. beer") delay(200) send(Beer(count++)) }} }} fun main() { val time = measureTimeMillis { runBlocking { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} 103
  78. fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while

    (isActive) { log("Tapping $count. beer") delay(200) send(Beer(count++)) }} }} fun main() { val time = measureTimeMillis { runBlocking { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} 104
  79. fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while

    (isActive) { log("Tapping $count. beer") delay(200) send(Beer(count++)) }} }} fun main() { val time = measureTimeMillis { runBlocking { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} 105
  80. fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while

    (isActive) { log("Tapping $count. beer") delay(200) send(Beer(count++)) }} }} fun main() { val time = measureTimeMillis { runBlocking { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} 106
  81. fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while

    (isActive) { log("Tapping $count. beer") delay(200) send(Beer(count++)) }} }} fun main() { val time = measureTimeMillis { runBlocking { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} 107
  82. fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while

    (isActive) { log("Tapping $count. beer") delay(200) send(Beer(count++)) }} }} fun main() { val time = measureTimeMillis { runBlocking { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} 108
  83. fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) { var count = 1 while

    (isActive) { log("Tapping $count. beer") delay(200) send(Beer(count++)) }} }} fun main() { val time = measureTimeMillis { runBlocking { log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) { orders(3).forEach { order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} 109
  84. • Cold streams • Blueprint • Operations: • emit() •

    terminal operators • RxJava like operators FLOW 110
  85. 111 fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) {{ var count = 1

    while (isActive) {{ log("Tapping $count. beer”)) delay(200) send(Beer(count++))) }} }} fun main() {{ val time = measureTimeMillis {{ runBlocking {{ log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) {{ orders(3).forEach { . order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }}
  86. 112 fun CoroutineScope.beersChannel() = produce(CoroutineName("Monika")) {{ var count = 1

    while (isActive) {{ log("Tapping $count. beer”)) delay(200) send(Beer(count++))) }} }} fun main() {{ val time = measureTimeMillis {{ runBlocking {{ log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) {{ orders(3).forEach { . order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }}
  87. 113 fun beersFlow() = produce(CoroutineName("Monika")) {{ var count = 1

    while (isActive) {{ log("Tapping $count. beer”)) delay(200) send(Beer(count++))) }} }} fun main() {{ val time = measureTimeMillis {{ runBlocking {{ log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) {{ orders(3).forEach { . order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }}
  88. 114 fun beersFlow() = flow {{ var count = 1

    while (isActive) {{ log("Tapping $count. beer”)) delay(200) send(Beer(count++))) }} }} fun main() {{ val time = measureTimeMillis {{ runBlocking {{ log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) {{ orders(3).forEach { . order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }}
  89. 115 fun beersFlow() = flow {{ var count = 1

    while (true) {{ log("Tapping $count. beer”)) delay(200) send(Beer(count++))) }} }} fun main() {{ val time = measureTimeMillis {{ runBlocking {{ log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) {{ orders(3).forEach { . order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }}
  90. 116 fun main() {{ val time = measureTimeMillis {{ runBlocking

    {{ log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) {{ orders(3).forEach { . order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} fun beersFlow() = flow {{ var count = 1 while (true) {{ log("Tapping $count. beer”)) delay(200) emit(Beer(count++)) }} }}
  91. 117 fun main() {{ val time = measureTimeMillis {{ runBlocking

    {{ log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) {{ orders(3).forEach { . order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} var count = 1 fun beersFlow() = flow {{ while (true) {{ log("Tapping $count. beer”)) delay(200) emit(Beer(count++)) }} }}
  92. 118 fun main() {{ val time = measureTimeMillis {{ runBlocking

    {{ log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) {{ orders(3).forEach { . order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} var count = 1 fun beersFlow() = flow {{ while (true) {{ log("Tapping $count. beer”)) delay(200) emit(Beer(count++)) }} }.flowOn(CoroutineName("Monika"))
  93. 119 fun main() {{ val time = measureTimeMillis {{ runBlocking

    {{ log("Stand opened") val beersChannel = beersChannel() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) {{ orders(3).forEach { . order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} var count = 1 fun beersFlow() = flow {{ while (true) {{ log("Tapping $count. beer”)) delay(200) emit(Beer(count++)) }} }.flowOn(CoroutineName("Monika"))
  94. 120 fun main() {{ val time = measureTimeMillis {{ runBlocking

    {{ log("Stand opened") val beersFlow = beersFlow() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) {{ orders(3).forEach { . order -> send(order) log("Order $order requested") log("Received ${beersChannel.receive()}") }} }} ... }} var count = 1 fun beersFlow() = flow {{ while (true) {{ log("Tapping $count. beer”)) delay(200) emit(Beer(count++)) }} }.flowOn(CoroutineName("Monika"))
  95. 121 fun main() {{ val time = measureTimeMillis {{ runBlocking

    {{ log("Stand opened") val beersFlow = beersFlow() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) {{ orders(3).forEach { . order -> send(order) log("Order $order requested") beersFlow.take(1).collect { . beer -> log(“Received . $beer”) }} }} }} ... }} var count = 1 fun beersFlow() = flow {{ while (true) {{ log("Tapping $count. beer”)) delay(200) emit(Beer(count++)) }} }.flowOn(CoroutineName("Monika"))
  96. 122 fun main() {{ val time = measureTimeMillis {{ runBlocking

    {{ log("Stand opened") val beersFlow = beersFlow() log(“Tap ready”) val ordersChannel = produce(CoroutineName("People")) {{ orders(3).forEach { . order -> send(order) log("Order $order requested") beersFlow.take(1).collect { . beer -> log(“Received. $beer”) }} }} }} ... }} var count = 1 fun beersFlow() = flow {{ while (true) {{ log("Tapping $count. beer”)) delay(200) emit(Beer(count++)) }} }.flowOn(CoroutineName("Monika"))
  97. 123

  98. 124

  99. 124

  100. ACTOR 126 sealed class QuantityCounterMsg { object IncQuantity : QuantityCounterMsg()

    object DcrQuantity : QuantityCounterMsg() class GetQuantity(val response: CompletableDeferred<Int>) : QuantityCounterMsg() }}
  101. ACTOR 127 sealed class QuantityCounterMsg { object IncQuantity : QuantityCounterMsg()

    object DcrQuantity : QuantityCounterMsg() class GetQuantity(val response: CompletableDeferred<Int>) : QuantityCounterMsg() }}
  102. ACTOR 128 sealed class QuantityCounterMsg { object IncQuantity : QuantityCounterMsg()

    object DcrQuantity : QuantityCounterMsg() class GetQuantity(val response: CompletableDeferred<Int>) : QuantityCounterMsg() }} fun CoroutineScope.quantityCounterActor() = actor<QuantityCounterMsg> { var quantity = 0 channel.consumeEach { message -> when (message) { is QuantityCounterMsg.IncQuantity -> quantity++ is QuantityCounterMsg.DcrQuantity -> if (quantity > 0) quantity-- is QuantityCounterMsg.GetQuantity -> message.response.complete(quantity) }} }} }}
  103. ACTOR 129 sealed class QuantityCounterMsg { object IncQuantity : QuantityCounterMsg()

    object DcrQuantity : QuantityCounterMsg() class GetQuantity(val response: CompletableDeferred<Int>) : QuantityCounterMsg() }} fun CoroutineScope.quantityCounterActor() = actor<QuantityCounterMsg> { var quantity = 0 channel.consumeEach { message -> when (message) { is QuantityCounterMsg.IncQuantity -> quantity++ is QuantityCounterMsg.DcrQuantity -> if (quantity > 0) quantity-- is QuantityCounterMsg.GetQuantity -> message.response.complete(quantity) }} }} }}
  104. fun CoroutineScope.quantityCounterActor() = actor<QuantityCounterMsg> { var quantity = 0 channel.consumeEach

    { message -> when (message) { is QuantityCounterMsg.IncQuantity -> quantity++ is QuantityCounterMsg.DcrQuantity -> if (quantity > 0) quantity-- is QuantityCounterMsg.GetQuantity -> message.response.complete(quantity) }} }} }} ACTOR 130 sealed class QuantityCounterMsg { object IncQuantity : QuantityCounterMsg() object DcrQuantity : QuantityCounterMsg() class GetQuantity(val response: CompletableDeferred<Int>) : QuantityCounterMsg() }}
  105. fun CoroutineScope.quantityCounterActor() = actor<QuantityCounterMsg> { var quantity = 0 channel.consumeEach

    { message -> when (message) { is QuantityCounterMsg.IncQuantity -> quantity++ is QuantityCounterMsg.DcrQuantity -> if (quantity > 0) quantity-- is QuantityCounterMsg.GetQuantity -> message.response.complete(quantity) }} }} }} ACTOR 131 sealed class QuantityCounterMsg { object IncQuantity : QuantityCounterMsg() object DcrQuantity : QuantityCounterMsg() class GetQuantity(val response: CompletableDeferred<Int>) : QuantityCounterMsg() }}
  106. fun CoroutineScope.quantityCounterActor() = actor<QuantityCounterMsg> { var quantity = 0 channel.consumeEach

    { message -> when (message) { is QuantityCounterMsg.IncQuantity -> quantity++ is QuantityCounterMsg.DcrQuantity -> if (quantity > 0) quantity-- is QuantityCounterMsg.GetQuantity -> message.response.complete(quantity) }} }} }} sealed class QuantityCounterMsg { object IncQuantity : QuantityCounterMsg() object DcrQuantity : QuantityCounterMsg() class GetQuantity(val response: CompletableDeferred<Int>) : QuantityCounterMsg() }} ACTOR 132 suspend fun massiveOrder(people: Int, requests: Int, action: suspend () -> Unit) { coroutineScope { List(people) { launch(CoroutineName("Person $it")) { repeat(requests) { action() } }} }} }} log("Created ${people * requests} requests") }}
  107. fun CoroutineScope.quantityCounterActor() = actor<QuantityCounterMsg> { var quantity = 0 channel.consumeEach

    { message -> when (message) { is QuantityCounterMsg.IncQuantity -> quantity++ is QuantityCounterMsg.DcrQuantity -> if (quantity > 0) quantity-- is QuantityCounterMsg.GetQuantity -> message.response.complete(quantity) }} }} }} sealed class QuantityCounterMsg { object IncQuantity : QuantityCounterMsg() object DcrQuantity : QuantityCounterMsg() class GetQuantity(val response: CompletableDeferred<Int>) : QuantityCounterMsg() }} ACTOR 133 suspend fun massiveOrder(people: Int, requests: Int, action: suspend () -> Unit) { coroutineScope { List(people) { launch(CoroutineName("Person $it")) { repeat(requests) { action() } }} }} }} log("Created ${people * requests} requests") }}
  108. fun CoroutineScope.quantityCounterActor() = actor<QuantityCounterMsg> { var quantity = 0 channel.consumeEach

    { message -> when (message) { is QuantityCounterMsg.IncQuantity -> quantity++ is QuantityCounterMsg.DcrQuantity -> if (quantity > 0) quantity-- is QuantityCounterMsg.GetQuantity -> message.response.complete(quantity) }} }} }} sealed class QuantityCounterMsg { object IncQuantity : QuantityCounterMsg() object DcrQuantity : QuantityCounterMsg() class GetQuantity(val response: CompletableDeferred<Int>) : QuantityCounterMsg() }} ACTOR 134 suspend fun massiveOrder(people: Int, requests: Int, action: suspend () -> Unit) { coroutineScope { List(people) { launch(CoroutineName("Person $it")) { repeat(requests) { action() } }} }} }} log("Created ${people * requests} requests") }}
  109. 135 fun main() { val time = measureTimeMillis { runBlocking

    { val quantityCounter = quantityCounterActor() massiveOrder(people = 8, requests = 3) { if (addHamburger()) { quantityCounter.send(QuantityCounterMsg.IncQuantity) } else { quantityCounter.send(QuantityCounterMsg.DcrQuantity) }} }} val quantity = CompletableDeferred<Int>().apply { quantityCounter.send(QuantityCounterMsg.GetQuantity(this)) }} quantityCounter.close() log("Hamburgers to make: ${quantity.await()}") processOrders(orders(quantity = quantity.await())) }} }} log("Orders processed in $time milliseconds") }}
  110. 136 fun main() { val time = measureTimeMillis { runBlocking

    { val quantityCounter = quantityCounterActor() massiveOrder(people = 8, requests = 3) { if (addHamburger()) { quantityCounter.send(QuantityCounterMsg.IncQuantity) } else { quantityCounter.send(QuantityCounterMsg.DcrQuantity) }} }} val quantity = CompletableDeferred<Int>().apply { quantityCounter.send(QuantityCounterMsg.GetQuantity(this)) }} quantityCounter.close() log("Hamburgers to make: ${quantity.await()}") processOrders(orders(quantity = quantity.await())) }} }} log("Orders processed in $time milliseconds") }}
  111. 137 fun main() { val time = measureTimeMillis { runBlocking

    { val quantityCounter = quantityCounterActor() massiveOrder(people = 8, requests = 3) { if (addHamburger()) { quantityCounter.send(QuantityCounterMsg.IncQuantity) } else { quantityCounter.send(QuantityCounterMsg.DcrQuantity) }} }} val quantity = CompletableDeferred<Int>().apply { quantityCounter.send(QuantityCounterMsg.GetQuantity(this)) }} quantityCounter.close() log("Hamburgers to make: ${quantity.await()}") processOrders(orders(quantity = quantity.await())) }} }} log("Orders processed in $time milliseconds") }}
  112. 138 fun main() { val time = measureTimeMillis { runBlocking

    { val quantityCounter = quantityCounterActor() massiveOrder(people = 8, requests = 3) { if (addHamburger()) { quantityCounter.send(QuantityCounterMsg.IncQuantity) } else { quantityCounter.send(QuantityCounterMsg.DcrQuantity) }} }} val quantity = CompletableDeferred<Int>().apply { quantityCounter.send(QuantityCounterMsg.GetQuantity(this)) }} quantityCounter.close() log("Hamburgers to make: ${quantity.await()}") processOrders(orders(quantity = quantity.await())) }} }} log("Orders processed in $time milliseconds") }}
  113. 139 fun main() { val time = measureTimeMillis { runBlocking

    { val quantityCounter = quantityCounterActor() massiveOrder(people = 8, requests = 3) { if (addHamburger()) { quantityCounter.send(QuantityCounterMsg.IncQuantity) } else { quantityCounter.send(QuantityCounterMsg.DcrQuantity) }} }} val quantity = CompletableDeferred<Int>().apply { quantityCounter.send(QuantityCounterMsg.GetQuantity(this)) }} quantityCounter.close() log("Hamburgers to make: ${quantity.await()}") processOrders(orders(quantity = quantity.await())) }} }} log("Orders processed in $time milliseconds") }} !!!
  114. 140 fun main() { val time = measureTimeMillis { runBlocking

    { val quantityCounter = quantityCounterActor() massiveOrder(people = 8, requests = 3) { if (addHamburger()) { quantityCounter.send(QuantityCounterMsg.IncQuantity) } else { quantityCounter.send(QuantityCounterMsg.DcrQuantity) }} }} val quantity = CompletableDeferred<Int>().apply { quantityCounter.send(QuantityCounterMsg.GetQuantity(this)) }} quantityCounter.close() log("Hamburgers to make: ${quantity.await()}") processOrders(orders(quantity = quantity.await())) }} }} log("Orders processed in $time milliseconds") }}
  115. 141

  116. 142

  117. 143

  118. 143

  119. • Selecting from channels • Selecting to send • Selecting

    deferred values Select expression makes it possible to await multiple suspending functions simultaneously and select the first one that becomes available. SELECT EXPRESSION 144
  120. • Selecting from channels • Selecting to send • Selecting

    deferred values Select expression makes it possible to await multiple suspending functions simultaneously and select the first one that becomes available. SELECT EXPRESSION 145
  121. private val microwave2 = actor<MicrowaveRequest>(CoroutineName("2.microwave")) {{ 146 SELECTING TO SEND

    }}} }} private val microwave1 = actor<MicrowaveRequest>(CoroutineName("1.microwave")) {{
  122. consumeEach { request -> delay(3000) //HEATING log("Stop heating ${request.bun.id}. bun")

    request.channel.send(request.bun) }} }} private val microwave1 = actor<MicrowaveRequest>(CoroutineName("1.microwave")) {{ private val microwave2 = actor<MicrowaveRequest>(CoroutineName("2.microwave")) {{ }}} 147 SELECTING TO SEND
  123. consumeEach { request -> delay(3000) //HEATING log("Stop heating ${request.bun.id}. bun")

    request.channel.send(request.bun) }} }} private val microwave1 = actor<MicrowaveRequest>(CoroutineName("1.microwave")) {{ private val microwave2 = actor<MicrowaveRequest>(CoroutineName("2.microwave")) {{ }}} 148 SELECTING TO SEND
  124. consumeEach { request -> delay(3000) //HEATING log("Stop heating ${request.bun.id}. bun")

    request.channel.send(request.bun) }} private val microwave1 = actor<MicrowaveRequest>(CoroutineName("1.microwave")) {{ }} private val microwave2 = actor<MicrowaveRequest>(CoroutineName("2.microwave")) {{ }}} 149 SELECTING TO SEND
  125. consumeEach { request -> delay(3000) //HEATING log("Stop heating ${request.bun.id}. bun")

    request.channel.send(request.bun) }} }} private val microwave1 = actor<MicrowaveRequest>(CoroutineName("1.microwave")) {{ private val microwave2 = actor<MicrowaveRequest>(CoroutineName("2.microwave")) {{ }}} 150 SELECTING TO SEND data class MicrowaveRequest( val bun: Bun, val channel: Channel<Bun> ))
  126. 151 SELECTING TO SEND data class MicrowaveRequest( val bun: Bun,

    val channel: Channel<Bun> )) consumeEach { request -> delay(3000) //HEATING log("Stop heating ${request.bun.id}. bun") request.channel.send(request.bun) }} }} private val microwave1 = actor<MicrowaveRequest>(CoroutineName("1.microwave")) {{ private val microwave2 = actor<MicrowaveRequest>(CoroutineName("2.microwave")) {{ }}}
  127. 152 }}} consumeEach { request -> delay(3000) //HEATING log("Stop heating

    ${request.bun.id}. bun") request.channel.send(request.bun) }}} data class MicrowaveRequest( val bun: Bun, val channel: Channel<Bun> )) consumeEach { request -> delay(3000) //HEATING log("Stop heating ${request.bun.id}. bun") request.channel.send(request.bun) }} }} private val microwave1 = actor<MicrowaveRequest>(CoroutineName("1.microwave")) {{ private val microwave2 = actor<MicrowaveRequest>(CoroutineName("2.microwave")) {{ }}} suspend fun heatBun(bun: Bun): Bun {{ val chan = Channel<Bun>() val heatedBun = select<Bun> {{ microwave1.onSend(MicrowaveRequest(bun, chan)) {{ log("Start heating ${bun.id}. bun in the 1. microwave") chan.receive() }} microwave2.onSend(MicrowaveRequest(bun, chan)) {{ log("Start heating ${bun.id}. bun in the 2. microwave") chan.receive() }} }} return heatedBun }}
  128. 153 }}} data class MicrowaveRequest( val bun: Bun, val channel:

    Channel<Bun> )) consumeEach { request -> delay(3000) //HEATING log("Stop heating ${request.bun.id}. bun") request.channel.send(request.bun) }} }} private val microwave1 = actor<MicrowaveRequest>(CoroutineName("1.microwave")) {{ private val microwave2 = actor<MicrowaveRequest>(CoroutineName("2.microwave")) {{ }}} consumeEach { request -> delay(3000) //HEATING log("Stop heating ${request.bun.id}. bun") request.channel.send(request.bun) }}} suspend fun heatBun(bun: Bun): Bun {{ val chan = Channel<Bun>() val heatedBun = select<Bun> {{ microwave1.onSend(MicrowaveRequest(bun, chan)) {{ log("Start heating ${bun.id}. bun in the 1. microwave") chan.receive() }} microwave2.onSend(MicrowaveRequest(bun, chan)) {{ log("Start heating ${bun.id}. bun in the 2. microwave") chan.receive() }} }} return heatedBun }}
  129. 154 consumeEach { request -> delay(3000) //HEATING log("Stop heating ${request.bun.id}.

    bun") request.channel.send(request.bun) }}} private val microwave2 = actor<MicrowaveRequest>(CoroutineName("2.microwave")) {{ }}} consumeEach { request -> delay(3000) //HEATING log("Stop heating ${request.bun.id}. bun") request.channel.send(request.bun) }} }} private val microwave1 = actor<MicrowaveRequest>(CoroutineName("1.microwave")) {{ suspend fun heatBun(bun: Bun): Bun {{ val chan = Channel<Bun>() val heatedBun = select<Bun> {{ microwave1.onSend(MicrowaveRequest(bun, chan)) {{ log("Start heating ${bun.id}. bun in the 1. microwave") chan.receive() }} microwave2.onSend(MicrowaveRequest(bun, chan)) {{ log("Start heating ${bun.id}. bun in the 2. microwave") chan.receive() }} }} return heatedBun }}
  130. 155 }}} consumeEach { request -> delay(3000) //HEATING log("Stop heating

    ${request.bun.id}. bun") request.channel.send(request.bun) }}} data class MicrowaveRequest( val bun: Bun, val channel: Channel<Bun> )) consumeEach { request -> delay(3000) //HEATING log("Stop heating ${request.bun.id}. bun") request.channel.send(request.bun) }} }} private val microwave1 = actor<MicrowaveRequest>(CoroutineName("1.microwave")) {{ private val microwave2 = actor<MicrowaveRequest>(CoroutineName("2.microwave")) {{ }}} suspend fun heatBun(bun: Bun): Bun {{ val chan = Channel<Bun>() val heatedBun = select<Bun> {{ microwave1.onSend(MicrowaveRequest(bun, chan)) {{ log("Start heating ${bun.id}. bun in the 1. microwave") chan.receive() }} microwave2.onSend(MicrowaveRequest(bun, chan)) {{ log("Start heating ${bun.id}. bun in the 2. microwave") chan.receive() }} }} return heatedBun }}
  131. 156

  132. 157

  133. 158

  134. 159

  135. 160

  136. 161

  137. 162

  138. 163

  139. 164

  140. REFERENCES • Kotlin coroutines documentation • Jag Saund. Kotlin: Diving

    in to Coroutines and Channels • Max's Tech. CPU Cores VS Threads - Explained • Elye. Understanding suspend function of Kotlin Coroutines 169