KEMBAR78
Coroutines in Kotlin | PPTX
Coroutines
in Kotlin
September 2017 - Alexey Soshin @ Gett
Kotlin in 1 minute
1. Developed by JetBrains (IntelliJ authors)
2. Powers all JetBrains tools
3. Open source
4. 100% interoperable with Java
5. First class citizen language on Android
6. Awesome modern language
7. Provides
a. Null safety
Concurrency
Think of concurrency as “Being able to do something else while you wait”
Concurrency suddenly matters, because modern systems spend a lot of their time on waiting:
● For memory
● For network
● For disk
That’s even before we start considering higher level options such as databases, remote services,
etc
Different concurrency models
● Multi threaded model
● Event loop
○ NodeJS in JavaScript
○ Vertx in Java
● CSP (communicating sequential processes)
○ go and channels in Go
○ Quasar in Java
● Actor model
○ Erlang
Limitations of spawning threads
● Each new Java thread consumes about 1MB of memory
● If we spawn thread for each request, we will eventually run out of available memory
○ Demo
● If we limit number of simultaneously spawned threads, we introduce a non-flexible
bottleneck in our system
○ Demo
Coroutines in Kotlin
● One of the major requirements from a modern language is to have concurrency solution
in place
● Kotlin async/await, channels and actors are not keywords, but simple functions calls
● Library developers are welcome to provide their own coroutines implementation
● JetBrains supply their own implementation as part of KotlinX
● As of Kotlin 1.1 coroutines are still an experimental feature
Starting coroutines and waiting for results
1. val job = async(CommonPool) { ... }
a. Launches coroutine that returns a result
2. val job = launch(CommonPool) { … }
a. Launches coroutine that doesn’t return any result (background job)
3. job.join()
a. Tells current coroutine to wait for job to execute
4. val result = job.await()
a. Tells current coroutine to wait, and returns its result
b. Example
Coroutines limitations
1. Since behind the scenes coroutines depend on event loop, coroutine that is CPU bound
may not let other coroutines execute
2. This may result in starvation
a. Example
Thread 1: coroutine 1
...
Thread 4: coroutine 4
coroutine 5 coroutine 6 Waiting...
Let it go: yield()
1. yield()
a. Resolves aforementioned problem by giving control back to the coroutine scheduler
b. This is only necessary if you don’t have calls to other suspending methods
c. Example
coroutine 4 continuesThread 4: coroutine 4 => yield coroutine 5
Cancelling coroutines
1. How do you cancel a running task in Java?
a. Hint: Future.cancel() may not work
b. Hint: pool.shutdownNow() may not work
c. Read more
2. Kotlin: job.cancel()
a. Asks nicely to cancel currently running coroutine
b. As in previous example, if coroutine never suspends, it cannot be cancelled.
Handling timeouts
1. How do you set a timeout for a Thread in Java
a. Hint: Same as cancel(), won’t always work as you expect
b. Read more
2. Kotlin: withTimeout(time, unit) { … }
a. While in context of coroutine, will throw TimeoutException if timeout has been reached, and
coroutine didn’t produce any results yet
b. Example
Coroutines hierarchy
1. Up until now we supplied CommonPool as the only argument for coroutine builder
function
a. async(CommonPool)
b. launch(CommonPool)
2. But builders also receive other arguments
3. For example, you can specify parent coroutine, that will able to cancel simultaneosly all
coroutines underneath it:
a. async(CommonPool + parentJob)
b. Example
Producers
1. produce(CommonPool) { … }
a. Will create a coroutine with outbound channel
b. Channel is a stream of values produced by the coroutine
2. select { … }
a. Lets you listen to numerous outbound channels, and act accordingly
b. select is a expression, so getting its value is simple:
i. val result = select { … }
c. Example
Actors
1. actor<String>(CommonPool, capacity = 100) { … }
a. Like producers, actors are coroutines bound to a channel
b. This time the channel is inbound. You have a clear way to send messages to actor, but how do you
get answers is up to you
c. That’s unlike some other Actor implementations, where actor has both inbound and outbound
mailboxes
d. Also, note that in Kotlin, the mailbox is bounded by capacity
e. Example
Questions?
Reading material
https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md
https://kotlinlang.org/docs/tutorials/coroutines-basic-jvm.html
https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md
https://blog.simon-wirtz.de/kotlin-coroutines-guide/
Examples: https://github.com/AlexeySoshin/KotlinCoroutinesIntro
Follow me
https://github.com/alexeysoshin
https://medium.com/@alexey.soshin/
https://stackoverflow.com/users/5985853/alexey-soshin
https://www.quora.com/profile/Alexey-Soshin
Or simply reach out by email: alexey.soshin@gmail.com

Coroutines in Kotlin

  • 1.
  • 2.
    Kotlin in 1minute 1. Developed by JetBrains (IntelliJ authors) 2. Powers all JetBrains tools 3. Open source 4. 100% interoperable with Java 5. First class citizen language on Android 6. Awesome modern language 7. Provides a. Null safety
  • 3.
    Concurrency Think of concurrencyas “Being able to do something else while you wait” Concurrency suddenly matters, because modern systems spend a lot of their time on waiting: ● For memory ● For network ● For disk That’s even before we start considering higher level options such as databases, remote services, etc
  • 4.
    Different concurrency models ●Multi threaded model ● Event loop ○ NodeJS in JavaScript ○ Vertx in Java ● CSP (communicating sequential processes) ○ go and channels in Go ○ Quasar in Java ● Actor model ○ Erlang
  • 5.
    Limitations of spawningthreads ● Each new Java thread consumes about 1MB of memory ● If we spawn thread for each request, we will eventually run out of available memory ○ Demo ● If we limit number of simultaneously spawned threads, we introduce a non-flexible bottleneck in our system ○ Demo
  • 6.
    Coroutines in Kotlin ●One of the major requirements from a modern language is to have concurrency solution in place ● Kotlin async/await, channels and actors are not keywords, but simple functions calls ● Library developers are welcome to provide their own coroutines implementation ● JetBrains supply their own implementation as part of KotlinX ● As of Kotlin 1.1 coroutines are still an experimental feature
  • 7.
    Starting coroutines andwaiting for results 1. val job = async(CommonPool) { ... } a. Launches coroutine that returns a result 2. val job = launch(CommonPool) { … } a. Launches coroutine that doesn’t return any result (background job) 3. job.join() a. Tells current coroutine to wait for job to execute 4. val result = job.await() a. Tells current coroutine to wait, and returns its result b. Example
  • 8.
    Coroutines limitations 1. Sincebehind the scenes coroutines depend on event loop, coroutine that is CPU bound may not let other coroutines execute 2. This may result in starvation a. Example Thread 1: coroutine 1 ... Thread 4: coroutine 4 coroutine 5 coroutine 6 Waiting...
  • 9.
    Let it go:yield() 1. yield() a. Resolves aforementioned problem by giving control back to the coroutine scheduler b. This is only necessary if you don’t have calls to other suspending methods c. Example coroutine 4 continuesThread 4: coroutine 4 => yield coroutine 5
  • 10.
    Cancelling coroutines 1. Howdo you cancel a running task in Java? a. Hint: Future.cancel() may not work b. Hint: pool.shutdownNow() may not work c. Read more 2. Kotlin: job.cancel() a. Asks nicely to cancel currently running coroutine b. As in previous example, if coroutine never suspends, it cannot be cancelled.
  • 11.
    Handling timeouts 1. Howdo you set a timeout for a Thread in Java a. Hint: Same as cancel(), won’t always work as you expect b. Read more 2. Kotlin: withTimeout(time, unit) { … } a. While in context of coroutine, will throw TimeoutException if timeout has been reached, and coroutine didn’t produce any results yet b. Example
  • 12.
    Coroutines hierarchy 1. Upuntil now we supplied CommonPool as the only argument for coroutine builder function a. async(CommonPool) b. launch(CommonPool) 2. But builders also receive other arguments 3. For example, you can specify parent coroutine, that will able to cancel simultaneosly all coroutines underneath it: a. async(CommonPool + parentJob) b. Example
  • 13.
    Producers 1. produce(CommonPool) {… } a. Will create a coroutine with outbound channel b. Channel is a stream of values produced by the coroutine 2. select { … } a. Lets you listen to numerous outbound channels, and act accordingly b. select is a expression, so getting its value is simple: i. val result = select { … } c. Example
  • 14.
    Actors 1. actor<String>(CommonPool, capacity= 100) { … } a. Like producers, actors are coroutines bound to a channel b. This time the channel is inbound. You have a clear way to send messages to actor, but how do you get answers is up to you c. That’s unlike some other Actor implementations, where actor has both inbound and outbound mailboxes d. Also, note that in Kotlin, the mailbox is bounded by capacity e. Example
  • 15.
  • 16.
  • 17.