SlideShare a Scribd company logo
1 of 145
Download to read offline
elizarov at JetBrains
Roman Elizarov
Introduction to Coroutines
Asynchronous
programming
How do we write code that waits
for something most of the time?
A toy problem
Kotlin fun requestToken(): Token {
// makes request for a token & waits
return token // returns result when received
}
1
fun requestToken(): Token { … }
fun createPost(token: Token, item: Item): Post {
// sends item to the server & waits
return post // returns resulting post
}
A toy problem
2
Kotlin
fun requestToken(): Token { … }
fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) {
// does some local processing of result
}
A toy problem
3
Kotlin
fun requestToken(): Token { … }
fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
A toy problem
fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
1
2
3
Can be done with
threads!
Kotlin
fun requestToken(): Token {
// makes request for a token
// blocks the thread waiting for result
return token // returns result when received
}
fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
Threads
fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
Is anything wrong with it?
How many threads we can have?
100 🙂
How many threads we can have?
1000 😅
How many threads we can have?
10 000 😩
How many threads we can have?
100 000 😵
Callbacks to the rescue
Sort of …
Callbacks: before
fun requestToken(): Token {
// makes request for a token & waits
return token // returns result when received
}
1
Callbacks: after
fun requestTokenAsync(cb: (Token) -> Unit) {
// makes request for a token, invokes callback when done
// returns immediately
}
1
callback
Callbacks: before
fun requestTokenAsync(cb: (Token) -> Unit) { … }
fun createPost(token: Token, item: Item): Post {
// sends item to the server & waits
return post // returns resulting post
}
2
Callbacks: after
fun requestTokenAsync(cb: (Token) -> Unit) { … }
fun createPostAsync(token: Token, item: Item,
cb: (Post) -> Unit) {
// sends item to the server, invokes callback when done
// returns immediately
}
2
callback
Callbacks: before
fun requestTokenAsync(cb: (Token) -> Unit) { … }
fun createPostAsync(token: Token, item: Item,
cb: (Post) -> Unit) { … }
fun processPost(post: Post) { … }
fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
Callbacks: after
fun requestTokenAsync(cb: (Token) -> Unit) { … }
fun createPostAsync(token: Token, item: Item,
cb: (Post) -> Unit) { … }
fun processPost(post: Post) { … }
fun postItem(item: Item) {
requestTokenAsync { token ->
createPostAsync(token, item) { post ->
processPost(post)
}
}
}
aka “callback hell”
This is simplified. Handling
exceptions makes it a real mess
Futures/Promises/Rx
to the rescue
Sort of …
Futures: before
fun requestTokenAsync(cb: (Token) -> Unit) {
// makes request for a token, invokes callback when done
// returns immediately
}
1
Futures: after
fun requestTokenAsync(): Promise<Token> {
// makes request for a token
// returns promise for a future result immediately
}
1
future
Futures: before
fun requestTokenAsync(): Promise<Token> { … }
fun createPostAsync(token: Token, item: Item,
cb: (Post) -> Unit) {
// sends item to the server, invokes callback when done
// returns immediately
}
2
Futures: after
fun requestTokenAsync(): Promise<Token> { … }
fun createPostAsync(token: Token, item: Item): Promise<Post> {
// sends item to the server
// returns promise for a future result immediately
}
future
2
Futures: before
fun requestTokenAsync(): Promise<Token> { … }
fun createPostAsync(token: Token, item: Item): Promise<Post> …
fun processPost(post: Post) { … }
fun postItem(item: Item) {
requestTokenAsync { token ->
createPostAsync(token, item) { post ->
processPost(post)
}
}
}
Futures: after
fun requestTokenAsync(): Promise<Token> { … }
fun createPostAsync(token: Token, item: Item): Promise<Post> …
fun processPost(post: Post) { … }
fun postItem(item: Item) {
requestTokenAsync()
.thenCompose { token -> createPostAsync(token, item) }
.thenAccept { post -> processPost(post) }
}
Composable &
propagates exceptions
No nesting indentation
Futures: after
fun requestTokenAsync(): Promise<Token> { … }
fun createPostAsync(token: Token, item: Item): Promise<Post> …
fun processPost(post: Post) { … }
fun postItem(item: Item) {
requestTokenAsync()
.thenCompose { token -> createPostAsync(token, item) }
.thenAccept { post -> processPost(post) }
}
But all those combinators…
Kotlin coroutines to the rescue
Let’s get real
Coroutines: before
fun requestTokenAsync(): Promise<Token> {
// makes request for a token
// returns promise for a future result immediately
}
1
Coroutines: after
suspend fun requestToken(): Token {
// makes request for a token & suspends
return token // returns result when received
}
1
Coroutines: after
suspend fun requestToken(): Token {
// makes request for a token & suspends
return token // returns result when received
}
1
natural signature
Coroutines: before
suspend fun requestToken(): Token { … }
fun createPostAsync(token: Token, item: Item): Promise<Post> {
// sends item to the server
// returns promise for a future result immediately
}
2
Coroutines: after
suspend fun requestToken(): Token { … }
suspend fun createPost(token: Token, item: Item): Post {
// sends item to the server & suspends
return post // returns result when received
}
2
Coroutines: before
suspend fun requestToken(): Token { … }
suspend fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
fun postItem(item: Item) {
requestTokenAsync()
.thenCompose { token -> createPostAsync(token, item) }
.thenAccept { post -> processPost(post) }
}
Coroutines: after
suspend fun requestToken(): Token { … }
suspend fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
suspend fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
Coroutines: after
suspend fun requestToken(): Token { … }
suspend fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
suspend fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
Like regular code
Coroutines: after
suspend fun requestToken(): Token { … }
suspend fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
suspend fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
suspension
points
• Regular loops
Bonus features
for ((token, item) in list) {
createPost(token, item)
}
• Regular exception handing
Bonus features
try {
createPost(token, item)
} catch (e: BadTokenException) {
…
}
• Regular higher-order functions
• forEach, let, apply, repeat, filter, map, use, etc
Bonus features
file.readLines().forEach { line ->
createPost(token, line.toItem())
}
Everything like in blocking code
Suspending functions
Retrofit async
interface Service {
fun createPost(token: Token, item: Item): Call<Post>
}
Retrofit async
interface Service {
fun createPost(token: Token, item: Item): Call<Post>
}
future
Retrofit async
interface Service {
fun createPost(token: Token, item: Item): Call<Post>
}
suspend fun createPost(token: Token, item: Item): Post =
serviceInstance.createPost(token, item).await()
Retrofit async
interface Service {
fun createPost(token: Token, item: Item): Call<Post>
}
suspend fun createPost(token: Token, item: Item): Post =
serviceInstance.createPost(token, item).await()
natural signature
Retrofit async
interface Service {
fun createPost(token: Token, item: Item): Call<Post>
}
suspend fun createPost(token: Token, item: Item): Post =
serviceInstance.createPost(token, item).await()
Suspending extension function
from integration library
Composition
Beyond sequential
val post = createPost(token, item)
Higher-order functions
val post = retryIO {
createPost(token, item)
}
Higher-order functions
val post = retryIO { createPost(token, item) }
suspend fun <T> retryIO(block: suspend () -> T): T {
var curDelay = 1000L // start with 1 sec
while (true) {
try {
return block()
} catch (e: IOException) {
e.printStackTrace() // log the error
}
delay(curDelay)
curDelay = (curDelay * 2).coerceAtMost(60000L)
}
}
Higher-order functions
val post = retryIO { createPost(token, item) }
suspend fun <T> retryIO(block: suspend () -> T): T {
var curDelay = 1000L // start with 1 sec
while (true) {
try {
return block()
} catch (e: IOException) {
e.printStackTrace() // log the error
}
delay(curDelay)
curDelay = (curDelay * 2).coerceAtMost(60000L)
}
}
Higher-order functions
val post = retryIO { createPost(token, item) }
suspend fun <T> retryIO(block: suspend () -> T): T {
var curDelay = 1000L // start with 1 sec
while (true) {
try {
return block()
} catch (e: IOException) {
e.printStackTrace() // log the error
}
delay(curDelay)
curDelay = (curDelay * 2).coerceAtMost(60000L)
}
}
suspending lambda
Higher-order functions
val post = retryIO { createPost(token, item) }
suspend fun <T> retryIO(block: suspend () -> T): T {
var curDelay = 1000L // start with 1 sec
while (true) {
try {
return block()
} catch (e: IOException) {
e.printStackTrace() // log the error
}
delay(curDelay)
curDelay = (curDelay * 2).coerceAtMost(60000L)
}
}
Everything like in blocking code
Higher-order functions
val post = retryIO { createPost(token, item) }
suspend fun <T> retryIO(block: suspend () -> T): T {
var curDelay = 1000L // start with 1 sec
while (true) {
try {
return block()
} catch (e: IOException) {
e.printStackTrace() // log the error
}
delay(curDelay)
curDelay = (curDelay * 2).coerceAtMost(60000L)
}
}
Coroutine builders
Coroutines revisited
suspend fun requestToken(): Token { … }
suspend fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
suspend fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
Coroutines revisited
suspend fun requestToken(): Token { … }
suspend fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
Coroutines revisited
suspend fun requestToken(): Token { … }
suspend fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
Error: Suspend function 'requestToken' should be called only from
a coroutine or another suspend function
Coroutines revisited
suspend fun requestToken(): Token { … }
suspend fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
Can suspend execution
Coroutines revisited
suspend fun requestToken(): Token { … }
suspend fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
Can suspend executionA regular function cannot
Coroutines revisited
suspend fun requestToken(): Token { … }
suspend fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
Can suspend executionA regular function cannot
One cannot simply invoke
a suspending function
Launch
fun postItem(item: Item) {
launch {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
}
coroutine builder
fun postItem(item: Item) {
launch {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
}
Fire and forget!
Returns immediately, coroutine
works in background thread pool
fun postItem(item: Item) {
launch {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
}
fun postItem(item: Item) {
launch(UI) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
}
UI Context
Just specify the context
fun postItem(item: Item) {
launch(UI) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
}
UI Context
And it gets executed on UI thread
Where’s the magic of launch?
fun launch(
context: CoroutineContext = DefaultDispatcher,
block: suspend () -> Unit
): Job { … }
A regular function
fun launch(
context: CoroutineContext = DefaultDispatcher,
block: suspend () -> Unit
): Job { … } suspending lambda
fun launch(
context: CoroutineContext = DefaultDispatcher,
block: suspend () -> Unit
): Job { … }
async / await
Kotlin-way
suspend fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
Kotlin
suspend fun requestToken(): Token { … }
suspend fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
async Task postItem(Item item) {
var token = await requestToken();
var post = await createPost(token, item);
processPost(post);
}
Classic-way
C# approach to the same problem
(also Python, TS, Dart, coming to JS)
C#
async Task<Token> requestToken() { … }
async Task<Post> createPost(Token token, Item item) { … }
void processPost(Post post) { … }
async Task postItem(Item item) {
var token = await requestToken();
var post = await createPost(token, item);
processPost(post);
}
Classic-way
mark with async
C#
async Task<Token> requestToken() { … }
async Task<Post> createPost(Token token, Item item) { … }
void processPost(Post post) { … }
async Task postItem(Item item) {
var token = await requestToken();
var post = await createPost(token, item);
processPost(post);
}
Classic-way
use await to suspend
C#
async Task<Token> requestToken() { … }
async Task<Post> createPost(Token token, Item item) { … }
void processPost(Post post) { … }
async Task postItem(Item item) {
var token = await requestToken();
var post = await createPost(token, item);
processPost(post);
}
Classic-way
C#
returns a future
async Task<Token> requestToken() { … }
async Task<Post> createPost(Token token, Item item) { … }
void processPost(Post post) { … }
Why no await keyword in Kotlin?
The problem with async
requestToken() VALID –> produces Task<Token>
await requestToken() VALID –> produces Token
concurrent behavior
sequential behavior
C#
C#
default
Kotlin suspending functions
are designed to imitate
sequential behavior
by default
Concurrency is hard
Concurrency has to be explicit
Kotlin approach to async
Concurrency where you need it
Use-case for async
async Task<Image> loadImageAsync(String name) { … }C#
Use-case for async
var promise1 = loadImageAsync(name1);
var promise2 = loadImageAsync(name2);
async Task<Image> loadImageAsync(String name) { … }
Start multiple operations
concurrently
C#
Use-case for async
var promise1 = loadImageAsync(name1);
var promise2 = loadImageAsync(name2);
var image1 = await promise1;
var image2 = await promise2;
async Task<Image> loadImageAsync(String name) { … }
and then wait for them
C#
Use-case for async
var result = combineImages(image1, image2);
C#
var promise1 = loadImageAsync(name1);
var promise2 = loadImageAsync(name2);
var image1 = await promise1;
var image2 = await promise2;
async Task<Image> loadImageAsync(String name) { … }
Kotlin async function
fun loadImageAsync(name: String): Deferred<Image> =
async { … }
Kotlin
Kotlin async function
fun loadImageAsync(name: String): Deferred<Image> =
async { … }
Kotlin
A regular function
Kotlin async function
fun loadImageAsync(name: String): Deferred<Image> =
async { … }
Kotlin’s future type
Kotlin
Kotlin async function
fun loadImageAsync(name: String): Deferred<Image> =
async { … }
async coroutine builder
Kotlin
Kotlin async function
fun loadImageAsync(name: String): Deferred<Image> =
async { … }
val deferred1 = loadImageAsync(name1)
val deferred2 = loadImageAsync(name2)
Start multiple operations
concurrently
Kotlin
Kotlin async function
fun loadImageAsync(name: String): Deferred<Image> =
async { … }
val deferred1 = loadImageAsync(name1)
val deferred2 = loadImageAsync(name2)
val image1 = deferred1.await()
val image2 = deferred2.await()
and then wait for them
await function
Suspends until deferred is complete
Kotlin
Kotlin async function
fun loadImageAsync(name: String): Deferred<Image> =
async { … }
val deferred1 = loadImageAsync(name1)
val deferred2 = loadImageAsync(name2)
val image1 = deferred1.await()
val image2 = deferred2.await()
val result = combineImages(image1, image2)
Kotlin
Using async function when needed
suspend fun loadImage(name: String): Image { … }
Is defined as suspending function, not async
Using async function when needed
suspend fun loadImage(name: String): Image { … }
suspend fun loadAndCombine(name1: String, name2: String): Image {
val deferred1 = async { loadImage(name1) }
val deferred2 = async { loadImage(name2) }
return combineImages(deferred1.await(), deferred2.await())
}
Using async function when needed
suspend fun loadImage(name: String): Image { … }
suspend fun loadAndCombine(name1: String, name2: String): Image {
val deferred1 = async { loadImage(name1) }
val deferred2 = async { loadImage(name2) }
return combineImages(deferred1.await(), deferred2.await())
}
Using async function when needed
suspend fun loadImage(name: String): Image { … }
suspend fun loadAndCombine(name1: String, name2: String): Image {
val deferred1 = async { loadImage(name1) }
val deferred2 = async { loadImage(name2) }
return combineImages(deferred1.await(), deferred2.await())
}
Using async function when needed
suspend fun loadImage(name: String): Image { … }
suspend fun loadAndCombine(name1: String, name2: String): Image {
val deferred1 = async { loadImage(name1) }
val deferred2 = async { loadImage(name2) }
return combineImages(deferred1.await(), deferred2.await())
}
Kotlin approach to async
requestToken() VALID –> produces Token
async { requestToken() } VALID –> produces Deferred<Token>
sequential behavior
concurrent behavior
Kotlin
Kotlin
default
Coroutines
What are coroutines
conceptually?
What are coroutines
conceptually?
Coroutines are like very light-weight threads
fun main(args: Array<String>) = runBlocking<Unit> {
val jobs = List(100_000) {
launch {
delay(1000L)
print(".")
}
}
jobs.forEach { it.join() }
}
Example
fun main(args: Array<String>) = runBlocking<Unit> {
val jobs = List(100_000) {
launch {
delay(1000L)
print(".")
}
}
jobs.forEach { it.join() }
}
Example
This coroutine builder runs coroutine
in the context of invoker thread
fun main(args: Array<String>) = runBlocking<Unit> {
val jobs = List(100_000) {
launch {
delay(1000L)
print(".")
}
}
jobs.forEach { it.join() }
}
Example
fun main(args: Array<String>) = runBlocking<Unit> {
val jobs = List(100_000) {
launch {
delay(1000L)
print(".")
}
}
jobs.forEach { it.join() }
}
Example
fun main(args: Array<String>) = runBlocking<Unit> {
val jobs = List(100_000) {
launch {
delay(1000L)
print(".")
}
}
jobs.forEach { it.join() }
}
Example
Suspends for 1 second
fun main(args: Array<String>) = runBlocking<Unit> {
val jobs = List(100_000) {
launch {
delay(1000L)
print(".")
}
}
jobs.forEach { it.join() }
}
Example
We can join a job
just like a thread
Demo
fun main(args: Array<String>) = runBlocking<Unit> {
val jobs = List(100_000) {
launch {
delay(1000L)
print(".")
}
}
jobs.forEach { it.join() }
}
Example
Try that with 100k threads!
Prints 100k dots after one second delay
fun main(args: Array<String>) = runBlocking<Unit> {
val jobs = List(100_000) {
launch {
delay(1000L)
print(".")
}
}
jobs.forEach { it.join() }
}
Example
fun main(args: Array<String>) {
val jobs = List(100_000) {
thread {
Thread.sleep(1000L)
print(".")
}
}
jobs.forEach { it.join() }
}
Example
Demo
fun main(args: Array<String>) {
val jobs = List(100_000) {
thread {
Thread.sleep(1000L)
print(".")
}
}
jobs.forEach { it.join() }
}
Example
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
Java interop
CompletableFuture<Image> loadImageAsync(String name) { … }Java
CompletableFuture<Image> loadImageAsync(String name) { … }
CompletableFuture<Image> loadAndCombineAsync(String name1,
String name2)
Imagine implementing it in Java…
Java
CompletableFuture<Image> loadImageAsync(String name) { … }
CompletableFuture<Image> loadAndCombineAsync(String name1,
String name2)
{
CompletableFuture<Image> future1 = loadImageAsync(name1);
CompletableFuture<Image> future2 = loadImageAsync(name2);
return future1.thenCompose(image1 ->
future2.thenCompose(image2 ->
CompletableFuture.supplyAsync(() ->
combineImages(image1, image2))));
}
Java
CompletableFuture<Image> loadImageAsync(String name) { … }
CompletableFuture<Image> loadAndCombineAsync(String name1,
String name2)
{
CompletableFuture<Image> future1 = loadImageAsync(name1);
CompletableFuture<Image> future2 = loadImageAsync(name2);
return future1.thenCompose(image1 ->
future2.thenCompose(image2 ->
CompletableFuture.supplyAsync(() ->
combineImages(image1, image2))));
}
Java
CompletableFuture<Image> loadImageAsync(String name) { … }
fun loadAndCombineAsync(
name1: String,
name2: String
): CompletableFuture<Image> =
future {
val future1 = loadImageAsync(name1)
val future2 = loadImageAsync(name2)
combineImages(future1.await(), future2.await())
}
Kotlin
Java
CompletableFuture<Image> loadImageAsync(String name) { … }
fun loadAndCombineAsync(
name1: String,
name2: String
): CompletableFuture<Image> =
future {
val future1 = loadImageAsync(name1)
val future2 = loadImageAsync(name2)
combineImages(future1.await(), future2.await())
}
Kotlin
Java
CompletableFuture<Image> loadImageAsync(String name) { … }
fun loadAndCombineAsync(
name1: String,
name2: String
): CompletableFuture<Image> =
future {
val future1 = loadImageAsync(name1)
val future2 = loadImageAsync(name2)
combineImages(future1.await(), future2.await())
}
future coroutine builder
Kotlin
Java
CompletableFuture<Image> loadImageAsync(String name) { … }
fun loadAndCombineAsync(
name1: String,
name2: String
): CompletableFuture<Image> =
future {
val future1 = loadImageAsync(name1)
val future2 = loadImageAsync(name2)
combineImages(future1.await(), future2.await())
}
Kotlin
Java
CompletableFuture<Image> loadImageAsync(String name) { … }
fun loadAndCombineAsync(
name1: String,
name2: String
): CompletableFuture<Image> =
future {
val future1 = loadImageAsync(name1)
val future2 = loadImageAsync(name2)
combineImages(future1.await(), future2.await())
}
Extension for Java’s CompletableFuture
Kotlin
Java
Beyond
asynchronous code
Fibonacci sequence
val fibonacci = buildSequence {
var cur = 1
var next = 1
while (true) {
yield(cur)
val tmp = cur + next
cur = next
next = tmp
}
}
val fibonacci = buildSequence {
var cur = 1
var next = 1
while (true) {
yield(cur)
val tmp = cur + next
cur = next
next = tmp
}
}
A coroutine builder with
restricted suspension
val fibonacci = buildSequence {
var cur = 1
var next = 1
while (true) {
yield(cur)
val tmp = cur + next
cur = next
next = tmp
}
}
A suspending function
The same building blocks
fun <T> buildSequence(
builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> { … }
fun <T> buildSequence(
builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> { … }
Result is a synchronous sequence
fun <T> buildSequence(
builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> { … }
Suspending lambda with receiver
fun <T> buildSequence(
builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> { … }
@RestrictsSuspension
abstract class SequenceBuilder<in T> {
abstract suspend fun yield(value: T)
}
Coroutine is restricted only to
suspending functions defined here
Synchronous
val fibonacci = buildSequence {
var cur = 1
var next = 1
while (true) {
yield(cur)
val tmp = cur + next
cur = next
next = tmp
}
}
val iter = fibonacci.iterator()
val fibonacci = buildSequence {
var cur = 1
var next = 1
while (true) {
yield(cur)
val tmp = cur + next
cur = next
next = tmp
}
}
val iter = fibonacci.iterator()
println(iter.next())
val fibonacci = buildSequence {
var cur = 1
var next = 1
while (true) {
yield(cur)
val tmp = cur + next
cur = next
next = tmp
}
}
val iter = fibonacci.iterator()
println(iter.next())
val fibonacci = buildSequence {
var cur = 1
var next = 1
while (true) {
yield(cur)
val tmp = cur + next
cur = next
next = tmp
}
}
val iter = fibonacci.iterator()
println(iter.next()) // 1
val fibonacci = buildSequence {
var cur = 1
var next = 1
while (true) {
yield(cur)
val tmp = cur + next
cur = next
next = tmp
}
}
val iter = fibonacci.iterator()
println(iter.next()) // 1
println(iter.next())
val fibonacci = buildSequence {
var cur = 1
var next = 1
while (true) {
yield(cur)
val tmp = cur + next
cur = next
next = tmp
}
}
val iter = fibonacci.iterator()
println(iter.next()) // 1
println(iter.next())
val fibonacci = buildSequence {
var cur = 1
var next = 1
while (true) {
yield(cur)
val tmp = cur + next
cur = next
next = tmp
}
}
val iter = fibonacci.iterator()
println(iter.next()) // 1
println(iter.next()) // 1
val fibonacci = buildSequence {
var cur = 1
var next = 1
while (true) {
yield(cur)
val tmp = cur + next
cur = next
next = tmp
}
}
val iter = fibonacci.iterator()
println(iter.next()) // 1
println(iter.next()) // 1
println(iter.next()) // 2
val fibonacci = buildSequence {
var cur = 1
var next = 1
while (true) {
yield(cur)
val tmp = cur + next
cur = next
next = tmp
}
}
val iter = fibonacci.iterator()
println(iter.next()) // 1
println(iter.next()) // 1
println(iter.next()) // 2
Synchronous with invoker
Library vs Language
Classic async
async/await
generate/yield
Keywords
Kotlin coroutines
suspend Modifier
Kotlin coroutines
Standard
library
Kotlin coroutines
Standard
library
kotlinx-coroutines
launch, async,
runBlocking, future, delay,
Job, Deferred, etc
http://github.com/kotlin/kotlinx.coroutines
Experimental status
Coroutines are here to stay
Backwards compatible inside 1.1 & 1.2
To be finalized in the future
#kotlinconf17
relizarov
elizarov at JetBrains
Roman Elizarov
Thank you
Any questions?

More Related Content

What's hot

炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
炎炎夏日學 Android 課程 -  Part1: Kotlin 語法介紹炎炎夏日學 Android 課程 -  Part1: Kotlin 語法介紹
炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹Johnny Sung
 
Utilizing kotlin flows in an android application
Utilizing kotlin flows in an android applicationUtilizing kotlin flows in an android application
Utilizing kotlin flows in an android applicationSeven Peaks Speaks
 
Android kotlin coroutines
Android kotlin coroutinesAndroid kotlin coroutines
Android kotlin coroutinesBipin Vayalu
 
Kotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a treeKotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a treeKai Koenig
 
Coroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth reviewCoroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth reviewDmytro Zaitsev
 
Kotlin - scope functions and collections
Kotlin - scope functions and collectionsKotlin - scope functions and collections
Kotlin - scope functions and collectionsWei-Shen Lu
 
Pros & cons of svelte
Pros & cons of sveltePros & cons of svelte
Pros & cons of svelteElenorWisozk
 
Kotlin Collections
Kotlin CollectionsKotlin Collections
Kotlin CollectionsHalil Özcan
 
Kotlin scope functions
Kotlin scope functionsKotlin scope functions
Kotlin scope functionsWaheed Nazir
 
Gitflow - Branching and Merging Flow for Git
Gitflow - Branching and Merging Flow for GitGitflow - Branching and Merging Flow for Git
Gitflow - Branching and Merging Flow for GitMaulik Shah
 
Java Deserialization Vulnerabilities - The Forgotten Bug Class
Java Deserialization Vulnerabilities - The Forgotten Bug ClassJava Deserialization Vulnerabilities - The Forgotten Bug Class
Java Deserialization Vulnerabilities - The Forgotten Bug ClassCODE WHITE GmbH
 
Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJSBrainhub
 
Understanding the Android System Server
Understanding the Android System ServerUnderstanding the Android System Server
Understanding the Android System ServerOpersys inc.
 

What's hot (20)

炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
炎炎夏日學 Android 課程 -  Part1: Kotlin 語法介紹炎炎夏日學 Android 課程 -  Part1: Kotlin 語法介紹
炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
 
Utilizing kotlin flows in an android application
Utilizing kotlin flows in an android applicationUtilizing kotlin flows in an android application
Utilizing kotlin flows in an android application
 
Android kotlin coroutines
Android kotlin coroutinesAndroid kotlin coroutines
Android kotlin coroutines
 
Kotlin
KotlinKotlin
Kotlin
 
Kotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a treeKotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a tree
 
Coroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth reviewCoroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth review
 
Learning Svelte
Learning SvelteLearning Svelte
Learning Svelte
 
Kotlin - scope functions and collections
Kotlin - scope functions and collectionsKotlin - scope functions and collections
Kotlin - scope functions and collections
 
Pros & cons of svelte
Pros & cons of sveltePros & cons of svelte
Pros & cons of svelte
 
Svelte
SvelteSvelte
Svelte
 
Svelte JS introduction
Svelte JS introductionSvelte JS introduction
Svelte JS introduction
 
Gradle Introduction
Gradle IntroductionGradle Introduction
Gradle Introduction
 
Svelte as a Reactive Web Framework
Svelte as a Reactive Web FrameworkSvelte as a Reactive Web Framework
Svelte as a Reactive Web Framework
 
Kotlin Collections
Kotlin CollectionsKotlin Collections
Kotlin Collections
 
Kotlin scope functions
Kotlin scope functionsKotlin scope functions
Kotlin scope functions
 
Gitflow - Branching and Merging Flow for Git
Gitflow - Branching and Merging Flow for GitGitflow - Branching and Merging Flow for Git
Gitflow - Branching and Merging Flow for Git
 
Kotlin - Better Java
Kotlin - Better JavaKotlin - Better Java
Kotlin - Better Java
 
Java Deserialization Vulnerabilities - The Forgotten Bug Class
Java Deserialization Vulnerabilities - The Forgotten Bug ClassJava Deserialization Vulnerabilities - The Forgotten Bug Class
Java Deserialization Vulnerabilities - The Forgotten Bug Class
 
Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJS
 
Understanding the Android System Server
Understanding the Android System ServerUnderstanding the Android System Server
Understanding the Android System Server
 

Similar to Introduction to Coroutines @ KotlinConf 2017

Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017Roman Elizarov
 
Fresh Async with Kotlin
Fresh Async with KotlinFresh Async with Kotlin
Fresh Async with KotlinC4Media
 
Dive into kotlins coroutines
Dive into kotlins coroutinesDive into kotlins coroutines
Dive into kotlins coroutinesFreddie Wang
 
Kotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenesKotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenesAnh Vu
 
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드NAVER Engineering
 
Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.UA Mobile
 
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando CoroutinesTDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutinestdc-globalcode
 
Programação assíncrona utilizando Coroutines
Programação assíncrona utilizando CoroutinesProgramação assíncrona utilizando Coroutines
Programação assíncrona utilizando CoroutinesDiego Gonçalves Santos
 
Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresiMasters
 
Kotlin coroutine - the next step for RxJava developer?
Kotlin coroutine - the next step for RxJava developer?Kotlin coroutine - the next step for RxJava developer?
Kotlin coroutine - the next step for RxJava developer?Artur Latoszewski
 
Kotlin의 코루틴은 어떻게 동작하는가
Kotlin의 코루틴은 어떻게 동작하는가Kotlin의 코루틴은 어떻게 동작하는가
Kotlin의 코루틴은 어떻게 동작하는가Chang W. Doh
 
Kotlin - Coroutine
Kotlin - CoroutineKotlin - Coroutine
Kotlin - CoroutineSean Tsai
 
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
TDC218SP | Trilha Kotlin - DSLs in a Kotlin WayTDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Waytdc-globalcode
 
C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴명신 김
 
Generics and Inference
Generics and InferenceGenerics and Inference
Generics and InferenceRichard Fox
 
Testing a 2D Platformer with Spock
Testing a 2D Platformer with SpockTesting a 2D Platformer with Spock
Testing a 2D Platformer with SpockAlexander Tarlinder
 

Similar to Introduction to Coroutines @ KotlinConf 2017 (20)

Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017
 
Fresh Async with Kotlin
Fresh Async with KotlinFresh Async with Kotlin
Fresh Async with Kotlin
 
Dive into kotlins coroutines
Dive into kotlins coroutinesDive into kotlins coroutines
Dive into kotlins coroutines
 
Kotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenesKotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenes
 
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
 
Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.
 
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando CoroutinesTDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
 
Programação assíncrona utilizando Coroutines
Programação assíncrona utilizando CoroutinesProgramação assíncrona utilizando Coroutines
Programação assíncrona utilizando Coroutines
 
Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan Soares
 
Kotlin coroutine - the next step for RxJava developer?
Kotlin coroutine - the next step for RxJava developer?Kotlin coroutine - the next step for RxJava developer?
Kotlin coroutine - the next step for RxJava developer?
 
Kotlin의 코루틴은 어떻게 동작하는가
Kotlin의 코루틴은 어떻게 동작하는가Kotlin의 코루틴은 어떻게 동작하는가
Kotlin의 코루틴은 어떻게 동작하는가
 
Current State of Coroutines
Current State of CoroutinesCurrent State of Coroutines
Current State of Coroutines
 
Kotlin - Coroutine
Kotlin - CoroutineKotlin - Coroutine
Kotlin - Coroutine
 
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
TDC218SP | Trilha Kotlin - DSLs in a Kotlin WayTDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
 
Coroutines in Kotlin
Coroutines in KotlinCoroutines in Kotlin
Coroutines in Kotlin
 
C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴
 
Generics and Inference
Generics and InferenceGenerics and Inference
Generics and Inference
 
FSE 2008
FSE 2008FSE 2008
FSE 2008
 
Testing a 2D Platformer with Spock
Testing a 2D Platformer with SpockTesting a 2D Platformer with Spock
Testing a 2D Platformer with Spock
 
Kotlin Generation
Kotlin GenerationKotlin Generation
Kotlin Generation
 

More from Roman Elizarov

Scale Up with Lock-Free Algorithms @ JavaOne
Scale Up with Lock-Free Algorithms @ JavaOneScale Up with Lock-Free Algorithms @ JavaOne
Scale Up with Lock-Free Algorithms @ JavaOneRoman Elizarov
 
Lock-free algorithms for Kotlin Coroutines
Lock-free algorithms for Kotlin CoroutinesLock-free algorithms for Kotlin Coroutines
Lock-free algorithms for Kotlin CoroutinesRoman Elizarov
 
Non blocking programming and waiting
Non blocking programming and waitingNon blocking programming and waiting
Non blocking programming and waitingRoman Elizarov
 
ACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems ReviewRoman Elizarov
 
Многопоточное Программирование - Теория и Практика
Многопоточное Программирование - Теория и ПрактикаМногопоточное Программирование - Теория и Практика
Многопоточное Программирование - Теория и ПрактикаRoman Elizarov
 
Wait for your fortune without Blocking!
Wait for your fortune without Blocking!Wait for your fortune without Blocking!
Wait for your fortune without Blocking!Roman Elizarov
 
ACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems ReviewRoman Elizarov
 
ACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems ReviewRoman Elizarov
 
Why GC is eating all my CPU?
Why GC is eating all my CPU?Why GC is eating all my CPU?
Why GC is eating all my CPU?Roman Elizarov
 
Многопоточные Алгоритмы (для BitByte 2014)
Многопоточные Алгоритмы (для BitByte 2014)Многопоточные Алгоритмы (для BitByte 2014)
Многопоточные Алгоритмы (для BitByte 2014)Roman Elizarov
 
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)Roman Elizarov
 
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems ReviewRoman Elizarov
 
Java Serialization Facts and Fallacies
Java Serialization Facts and FallaciesJava Serialization Facts and Fallacies
Java Serialization Facts and FallaciesRoman Elizarov
 
Millions quotes per second in pure java
Millions quotes per second in pure javaMillions quotes per second in pure java
Millions quotes per second in pure javaRoman Elizarov
 
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems ReviewRoman Elizarov
 
The theory of concurrent programming for a seasoned programmer
The theory of concurrent programming for a seasoned programmerThe theory of concurrent programming for a seasoned programmer
The theory of concurrent programming for a seasoned programmerRoman Elizarov
 
Пишем самый быстрый хеш для кэширования данных
Пишем самый быстрый хеш для кэширования данныхПишем самый быстрый хеш для кэширования данных
Пишем самый быстрый хеш для кэширования данныхRoman Elizarov
 

More from Roman Elizarov (18)

Scale Up with Lock-Free Algorithms @ JavaOne
Scale Up with Lock-Free Algorithms @ JavaOneScale Up with Lock-Free Algorithms @ JavaOne
Scale Up with Lock-Free Algorithms @ JavaOne
 
Lock-free algorithms for Kotlin Coroutines
Lock-free algorithms for Kotlin CoroutinesLock-free algorithms for Kotlin Coroutines
Lock-free algorithms for Kotlin Coroutines
 
Non blocking programming and waiting
Non blocking programming and waitingNon blocking programming and waiting
Non blocking programming and waiting
 
ACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems Review
 
Многопоточное Программирование - Теория и Практика
Многопоточное Программирование - Теория и ПрактикаМногопоточное Программирование - Теория и Практика
Многопоточное Программирование - Теория и Практика
 
Wait for your fortune without Blocking!
Wait for your fortune without Blocking!Wait for your fortune without Blocking!
Wait for your fortune without Blocking!
 
ACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems Review
 
ACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems Review
 
Why GC is eating all my CPU?
Why GC is eating all my CPU?Why GC is eating all my CPU?
Why GC is eating all my CPU?
 
Многопоточные Алгоритмы (для BitByte 2014)
Многопоточные Алгоритмы (для BitByte 2014)Многопоточные Алгоритмы (для BitByte 2014)
Многопоточные Алгоритмы (для BitByte 2014)
 
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
 
DIY Java Profiling
DIY Java ProfilingDIY Java Profiling
DIY Java Profiling
 
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
 
Java Serialization Facts and Fallacies
Java Serialization Facts and FallaciesJava Serialization Facts and Fallacies
Java Serialization Facts and Fallacies
 
Millions quotes per second in pure java
Millions quotes per second in pure javaMillions quotes per second in pure java
Millions quotes per second in pure java
 
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
 
The theory of concurrent programming for a seasoned programmer
The theory of concurrent programming for a seasoned programmerThe theory of concurrent programming for a seasoned programmer
The theory of concurrent programming for a seasoned programmer
 
Пишем самый быстрый хеш для кэширования данных
Пишем самый быстрый хеш для кэширования данныхПишем самый быстрый хеш для кэширования данных
Пишем самый быстрый хеш для кэширования данных
 

Recently uploaded

How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 

Recently uploaded (20)

How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 

Introduction to Coroutines @ KotlinConf 2017

  • 1. elizarov at JetBrains Roman Elizarov Introduction to Coroutines
  • 3. How do we write code that waits for something most of the time?
  • 4. A toy problem Kotlin fun requestToken(): Token { // makes request for a token & waits return token // returns result when received } 1
  • 5. fun requestToken(): Token { … } fun createPost(token: Token, item: Item): Post { // sends item to the server & waits return post // returns resulting post } A toy problem 2 Kotlin
  • 6. fun requestToken(): Token { … } fun createPost(token: Token, item: Item): Post { … } fun processPost(post: Post) { // does some local processing of result } A toy problem 3 Kotlin
  • 7. fun requestToken(): Token { … } fun createPost(token: Token, item: Item): Post { … } fun processPost(post: Post) { … } A toy problem fun postItem(item: Item) { val token = requestToken() val post = createPost(token, item) processPost(post) } 1 2 3 Can be done with threads! Kotlin
  • 8. fun requestToken(): Token { // makes request for a token // blocks the thread waiting for result return token // returns result when received } fun createPost(token: Token, item: Item): Post { … } fun processPost(post: Post) { … } Threads fun postItem(item: Item) { val token = requestToken() val post = createPost(token, item) processPost(post) } Is anything wrong with it?
  • 9. How many threads we can have? 100 🙂
  • 10. How many threads we can have? 1000 😅
  • 11. How many threads we can have? 10 000 😩
  • 12. How many threads we can have? 100 000 😵
  • 13. Callbacks to the rescue Sort of …
  • 14. Callbacks: before fun requestToken(): Token { // makes request for a token & waits return token // returns result when received } 1
  • 15. Callbacks: after fun requestTokenAsync(cb: (Token) -> Unit) { // makes request for a token, invokes callback when done // returns immediately } 1 callback
  • 16. Callbacks: before fun requestTokenAsync(cb: (Token) -> Unit) { … } fun createPost(token: Token, item: Item): Post { // sends item to the server & waits return post // returns resulting post } 2
  • 17. Callbacks: after fun requestTokenAsync(cb: (Token) -> Unit) { … } fun createPostAsync(token: Token, item: Item, cb: (Post) -> Unit) { // sends item to the server, invokes callback when done // returns immediately } 2 callback
  • 18. Callbacks: before fun requestTokenAsync(cb: (Token) -> Unit) { … } fun createPostAsync(token: Token, item: Item, cb: (Post) -> Unit) { … } fun processPost(post: Post) { … } fun postItem(item: Item) { val token = requestToken() val post = createPost(token, item) processPost(post) }
  • 19. Callbacks: after fun requestTokenAsync(cb: (Token) -> Unit) { … } fun createPostAsync(token: Token, item: Item, cb: (Post) -> Unit) { … } fun processPost(post: Post) { … } fun postItem(item: Item) { requestTokenAsync { token -> createPostAsync(token, item) { post -> processPost(post) } } } aka “callback hell” This is simplified. Handling exceptions makes it a real mess
  • 21. Futures: before fun requestTokenAsync(cb: (Token) -> Unit) { // makes request for a token, invokes callback when done // returns immediately } 1
  • 22. Futures: after fun requestTokenAsync(): Promise<Token> { // makes request for a token // returns promise for a future result immediately } 1 future
  • 23. Futures: before fun requestTokenAsync(): Promise<Token> { … } fun createPostAsync(token: Token, item: Item, cb: (Post) -> Unit) { // sends item to the server, invokes callback when done // returns immediately } 2
  • 24. Futures: after fun requestTokenAsync(): Promise<Token> { … } fun createPostAsync(token: Token, item: Item): Promise<Post> { // sends item to the server // returns promise for a future result immediately } future 2
  • 25. Futures: before fun requestTokenAsync(): Promise<Token> { … } fun createPostAsync(token: Token, item: Item): Promise<Post> … fun processPost(post: Post) { … } fun postItem(item: Item) { requestTokenAsync { token -> createPostAsync(token, item) { post -> processPost(post) } } }
  • 26. Futures: after fun requestTokenAsync(): Promise<Token> { … } fun createPostAsync(token: Token, item: Item): Promise<Post> … fun processPost(post: Post) { … } fun postItem(item: Item) { requestTokenAsync() .thenCompose { token -> createPostAsync(token, item) } .thenAccept { post -> processPost(post) } } Composable & propagates exceptions No nesting indentation
  • 27. Futures: after fun requestTokenAsync(): Promise<Token> { … } fun createPostAsync(token: Token, item: Item): Promise<Post> … fun processPost(post: Post) { … } fun postItem(item: Item) { requestTokenAsync() .thenCompose { token -> createPostAsync(token, item) } .thenAccept { post -> processPost(post) } } But all those combinators…
  • 28. Kotlin coroutines to the rescue Let’s get real
  • 29. Coroutines: before fun requestTokenAsync(): Promise<Token> { // makes request for a token // returns promise for a future result immediately } 1
  • 30. Coroutines: after suspend fun requestToken(): Token { // makes request for a token & suspends return token // returns result when received } 1
  • 31. Coroutines: after suspend fun requestToken(): Token { // makes request for a token & suspends return token // returns result when received } 1 natural signature
  • 32. Coroutines: before suspend fun requestToken(): Token { … } fun createPostAsync(token: Token, item: Item): Promise<Post> { // sends item to the server // returns promise for a future result immediately } 2
  • 33. Coroutines: after suspend fun requestToken(): Token { … } suspend fun createPost(token: Token, item: Item): Post { // sends item to the server & suspends return post // returns result when received } 2
  • 34. Coroutines: before suspend fun requestToken(): Token { … } suspend fun createPost(token: Token, item: Item): Post { … } fun processPost(post: Post) { … } fun postItem(item: Item) { requestTokenAsync() .thenCompose { token -> createPostAsync(token, item) } .thenAccept { post -> processPost(post) } }
  • 35. Coroutines: after suspend fun requestToken(): Token { … } suspend fun createPost(token: Token, item: Item): Post { … } fun processPost(post: Post) { … } suspend fun postItem(item: Item) { val token = requestToken() val post = createPost(token, item) processPost(post) }
  • 36. Coroutines: after suspend fun requestToken(): Token { … } suspend fun createPost(token: Token, item: Item): Post { … } fun processPost(post: Post) { … } suspend fun postItem(item: Item) { val token = requestToken() val post = createPost(token, item) processPost(post) } Like regular code
  • 37. Coroutines: after suspend fun requestToken(): Token { … } suspend fun createPost(token: Token, item: Item): Post { … } fun processPost(post: Post) { … } suspend fun postItem(item: Item) { val token = requestToken() val post = createPost(token, item) processPost(post) } suspension points
  • 38. • Regular loops Bonus features for ((token, item) in list) { createPost(token, item) }
  • 39. • Regular exception handing Bonus features try { createPost(token, item) } catch (e: BadTokenException) { … }
  • 40. • Regular higher-order functions • forEach, let, apply, repeat, filter, map, use, etc Bonus features file.readLines().forEach { line -> createPost(token, line.toItem()) } Everything like in blocking code
  • 42. Retrofit async interface Service { fun createPost(token: Token, item: Item): Call<Post> }
  • 43. Retrofit async interface Service { fun createPost(token: Token, item: Item): Call<Post> } future
  • 44. Retrofit async interface Service { fun createPost(token: Token, item: Item): Call<Post> } suspend fun createPost(token: Token, item: Item): Post = serviceInstance.createPost(token, item).await()
  • 45. Retrofit async interface Service { fun createPost(token: Token, item: Item): Call<Post> } suspend fun createPost(token: Token, item: Item): Post = serviceInstance.createPost(token, item).await() natural signature
  • 46. Retrofit async interface Service { fun createPost(token: Token, item: Item): Call<Post> } suspend fun createPost(token: Token, item: Item): Post = serviceInstance.createPost(token, item).await() Suspending extension function from integration library
  • 48. val post = createPost(token, item)
  • 49. Higher-order functions val post = retryIO { createPost(token, item) }
  • 50. Higher-order functions val post = retryIO { createPost(token, item) } suspend fun <T> retryIO(block: suspend () -> T): T { var curDelay = 1000L // start with 1 sec while (true) { try { return block() } catch (e: IOException) { e.printStackTrace() // log the error } delay(curDelay) curDelay = (curDelay * 2).coerceAtMost(60000L) } }
  • 51. Higher-order functions val post = retryIO { createPost(token, item) } suspend fun <T> retryIO(block: suspend () -> T): T { var curDelay = 1000L // start with 1 sec while (true) { try { return block() } catch (e: IOException) { e.printStackTrace() // log the error } delay(curDelay) curDelay = (curDelay * 2).coerceAtMost(60000L) } }
  • 52. Higher-order functions val post = retryIO { createPost(token, item) } suspend fun <T> retryIO(block: suspend () -> T): T { var curDelay = 1000L // start with 1 sec while (true) { try { return block() } catch (e: IOException) { e.printStackTrace() // log the error } delay(curDelay) curDelay = (curDelay * 2).coerceAtMost(60000L) } } suspending lambda
  • 53. Higher-order functions val post = retryIO { createPost(token, item) } suspend fun <T> retryIO(block: suspend () -> T): T { var curDelay = 1000L // start with 1 sec while (true) { try { return block() } catch (e: IOException) { e.printStackTrace() // log the error } delay(curDelay) curDelay = (curDelay * 2).coerceAtMost(60000L) } } Everything like in blocking code
  • 54. Higher-order functions val post = retryIO { createPost(token, item) } suspend fun <T> retryIO(block: suspend () -> T): T { var curDelay = 1000L // start with 1 sec while (true) { try { return block() } catch (e: IOException) { e.printStackTrace() // log the error } delay(curDelay) curDelay = (curDelay * 2).coerceAtMost(60000L) } }
  • 56. Coroutines revisited suspend fun requestToken(): Token { … } suspend fun createPost(token: Token, item: Item): Post { … } fun processPost(post: Post) { … } suspend fun postItem(item: Item) { val token = requestToken() val post = createPost(token, item) processPost(post) }
  • 57. Coroutines revisited suspend fun requestToken(): Token { … } suspend fun createPost(token: Token, item: Item): Post { … } fun processPost(post: Post) { … } fun postItem(item: Item) { val token = requestToken() val post = createPost(token, item) processPost(post) }
  • 58. Coroutines revisited suspend fun requestToken(): Token { … } suspend fun createPost(token: Token, item: Item): Post { … } fun processPost(post: Post) { … } fun postItem(item: Item) { val token = requestToken() val post = createPost(token, item) processPost(post) } Error: Suspend function 'requestToken' should be called only from a coroutine or another suspend function
  • 59. Coroutines revisited suspend fun requestToken(): Token { … } suspend fun createPost(token: Token, item: Item): Post { … } fun processPost(post: Post) { … } fun postItem(item: Item) { val token = requestToken() val post = createPost(token, item) processPost(post) } Can suspend execution
  • 60. Coroutines revisited suspend fun requestToken(): Token { … } suspend fun createPost(token: Token, item: Item): Post { … } fun processPost(post: Post) { … } fun postItem(item: Item) { val token = requestToken() val post = createPost(token, item) processPost(post) } Can suspend executionA regular function cannot
  • 61. Coroutines revisited suspend fun requestToken(): Token { … } suspend fun createPost(token: Token, item: Item): Post { … } fun processPost(post: Post) { … } fun postItem(item: Item) { val token = requestToken() val post = createPost(token, item) processPost(post) } Can suspend executionA regular function cannot One cannot simply invoke a suspending function
  • 62. Launch fun postItem(item: Item) { launch { val token = requestToken() val post = createPost(token, item) processPost(post) } } coroutine builder
  • 63. fun postItem(item: Item) { launch { val token = requestToken() val post = createPost(token, item) processPost(post) } } Fire and forget! Returns immediately, coroutine works in background thread pool
  • 64. fun postItem(item: Item) { launch { val token = requestToken() val post = createPost(token, item) processPost(post) } }
  • 65. fun postItem(item: Item) { launch(UI) { val token = requestToken() val post = createPost(token, item) processPost(post) } } UI Context Just specify the context
  • 66. fun postItem(item: Item) { launch(UI) { val token = requestToken() val post = createPost(token, item) processPost(post) } } UI Context And it gets executed on UI thread
  • 67. Where’s the magic of launch?
  • 68. fun launch( context: CoroutineContext = DefaultDispatcher, block: suspend () -> Unit ): Job { … } A regular function
  • 69. fun launch( context: CoroutineContext = DefaultDispatcher, block: suspend () -> Unit ): Job { … } suspending lambda
  • 70. fun launch( context: CoroutineContext = DefaultDispatcher, block: suspend () -> Unit ): Job { … }
  • 72. Kotlin-way suspend fun postItem(item: Item) { val token = requestToken() val post = createPost(token, item) processPost(post) } Kotlin suspend fun requestToken(): Token { … } suspend fun createPost(token: Token, item: Item): Post { … } fun processPost(post: Post) { … }
  • 73. async Task postItem(Item item) { var token = await requestToken(); var post = await createPost(token, item); processPost(post); } Classic-way C# approach to the same problem (also Python, TS, Dart, coming to JS) C# async Task<Token> requestToken() { … } async Task<Post> createPost(Token token, Item item) { … } void processPost(Post post) { … }
  • 74. async Task postItem(Item item) { var token = await requestToken(); var post = await createPost(token, item); processPost(post); } Classic-way mark with async C# async Task<Token> requestToken() { … } async Task<Post> createPost(Token token, Item item) { … } void processPost(Post post) { … }
  • 75. async Task postItem(Item item) { var token = await requestToken(); var post = await createPost(token, item); processPost(post); } Classic-way use await to suspend C# async Task<Token> requestToken() { … } async Task<Post> createPost(Token token, Item item) { … } void processPost(Post post) { … }
  • 76. async Task postItem(Item item) { var token = await requestToken(); var post = await createPost(token, item); processPost(post); } Classic-way C# returns a future async Task<Token> requestToken() { … } async Task<Post> createPost(Token token, Item item) { … } void processPost(Post post) { … }
  • 77. Why no await keyword in Kotlin? The problem with async requestToken() VALID –> produces Task<Token> await requestToken() VALID –> produces Token concurrent behavior sequential behavior C# C# default
  • 78. Kotlin suspending functions are designed to imitate sequential behavior by default Concurrency is hard Concurrency has to be explicit
  • 79. Kotlin approach to async Concurrency where you need it
  • 80. Use-case for async async Task<Image> loadImageAsync(String name) { … }C#
  • 81. Use-case for async var promise1 = loadImageAsync(name1); var promise2 = loadImageAsync(name2); async Task<Image> loadImageAsync(String name) { … } Start multiple operations concurrently C#
  • 82. Use-case for async var promise1 = loadImageAsync(name1); var promise2 = loadImageAsync(name2); var image1 = await promise1; var image2 = await promise2; async Task<Image> loadImageAsync(String name) { … } and then wait for them C#
  • 83. Use-case for async var result = combineImages(image1, image2); C# var promise1 = loadImageAsync(name1); var promise2 = loadImageAsync(name2); var image1 = await promise1; var image2 = await promise2; async Task<Image> loadImageAsync(String name) { … }
  • 84. Kotlin async function fun loadImageAsync(name: String): Deferred<Image> = async { … } Kotlin
  • 85. Kotlin async function fun loadImageAsync(name: String): Deferred<Image> = async { … } Kotlin A regular function
  • 86. Kotlin async function fun loadImageAsync(name: String): Deferred<Image> = async { … } Kotlin’s future type Kotlin
  • 87. Kotlin async function fun loadImageAsync(name: String): Deferred<Image> = async { … } async coroutine builder Kotlin
  • 88. Kotlin async function fun loadImageAsync(name: String): Deferred<Image> = async { … } val deferred1 = loadImageAsync(name1) val deferred2 = loadImageAsync(name2) Start multiple operations concurrently Kotlin
  • 89. Kotlin async function fun loadImageAsync(name: String): Deferred<Image> = async { … } val deferred1 = loadImageAsync(name1) val deferred2 = loadImageAsync(name2) val image1 = deferred1.await() val image2 = deferred2.await() and then wait for them await function Suspends until deferred is complete Kotlin
  • 90. Kotlin async function fun loadImageAsync(name: String): Deferred<Image> = async { … } val deferred1 = loadImageAsync(name1) val deferred2 = loadImageAsync(name2) val image1 = deferred1.await() val image2 = deferred2.await() val result = combineImages(image1, image2) Kotlin
  • 91. Using async function when needed suspend fun loadImage(name: String): Image { … } Is defined as suspending function, not async
  • 92. Using async function when needed suspend fun loadImage(name: String): Image { … } suspend fun loadAndCombine(name1: String, name2: String): Image { val deferred1 = async { loadImage(name1) } val deferred2 = async { loadImage(name2) } return combineImages(deferred1.await(), deferred2.await()) }
  • 93. Using async function when needed suspend fun loadImage(name: String): Image { … } suspend fun loadAndCombine(name1: String, name2: String): Image { val deferred1 = async { loadImage(name1) } val deferred2 = async { loadImage(name2) } return combineImages(deferred1.await(), deferred2.await()) }
  • 94. Using async function when needed suspend fun loadImage(name: String): Image { … } suspend fun loadAndCombine(name1: String, name2: String): Image { val deferred1 = async { loadImage(name1) } val deferred2 = async { loadImage(name2) } return combineImages(deferred1.await(), deferred2.await()) }
  • 95. Using async function when needed suspend fun loadImage(name: String): Image { … } suspend fun loadAndCombine(name1: String, name2: String): Image { val deferred1 = async { loadImage(name1) } val deferred2 = async { loadImage(name2) } return combineImages(deferred1.await(), deferred2.await()) }
  • 96. Kotlin approach to async requestToken() VALID –> produces Token async { requestToken() } VALID –> produces Deferred<Token> sequential behavior concurrent behavior Kotlin Kotlin default
  • 99. What are coroutines conceptually? Coroutines are like very light-weight threads
  • 100. fun main(args: Array<String>) = runBlocking<Unit> { val jobs = List(100_000) { launch { delay(1000L) print(".") } } jobs.forEach { it.join() } } Example
  • 101. fun main(args: Array<String>) = runBlocking<Unit> { val jobs = List(100_000) { launch { delay(1000L) print(".") } } jobs.forEach { it.join() } } Example This coroutine builder runs coroutine in the context of invoker thread
  • 102. fun main(args: Array<String>) = runBlocking<Unit> { val jobs = List(100_000) { launch { delay(1000L) print(".") } } jobs.forEach { it.join() } } Example
  • 103. fun main(args: Array<String>) = runBlocking<Unit> { val jobs = List(100_000) { launch { delay(1000L) print(".") } } jobs.forEach { it.join() } } Example
  • 104. fun main(args: Array<String>) = runBlocking<Unit> { val jobs = List(100_000) { launch { delay(1000L) print(".") } } jobs.forEach { it.join() } } Example Suspends for 1 second
  • 105. fun main(args: Array<String>) = runBlocking<Unit> { val jobs = List(100_000) { launch { delay(1000L) print(".") } } jobs.forEach { it.join() } } Example We can join a job just like a thread
  • 106. Demo
  • 107. fun main(args: Array<String>) = runBlocking<Unit> { val jobs = List(100_000) { launch { delay(1000L) print(".") } } jobs.forEach { it.join() } } Example Try that with 100k threads! Prints 100k dots after one second delay
  • 108. fun main(args: Array<String>) = runBlocking<Unit> { val jobs = List(100_000) { launch { delay(1000L) print(".") } } jobs.forEach { it.join() } } Example
  • 109. fun main(args: Array<String>) { val jobs = List(100_000) { thread { Thread.sleep(1000L) print(".") } } jobs.forEach { it.join() } } Example
  • 110. Demo
  • 111. fun main(args: Array<String>) { val jobs = List(100_000) { thread { Thread.sleep(1000L) print(".") } } jobs.forEach { it.join() } } Example Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
  • 114. CompletableFuture<Image> loadImageAsync(String name) { … } CompletableFuture<Image> loadAndCombineAsync(String name1, String name2) Imagine implementing it in Java… Java
  • 115. CompletableFuture<Image> loadImageAsync(String name) { … } CompletableFuture<Image> loadAndCombineAsync(String name1, String name2) { CompletableFuture<Image> future1 = loadImageAsync(name1); CompletableFuture<Image> future2 = loadImageAsync(name2); return future1.thenCompose(image1 -> future2.thenCompose(image2 -> CompletableFuture.supplyAsync(() -> combineImages(image1, image2)))); } Java
  • 116. CompletableFuture<Image> loadImageAsync(String name) { … } CompletableFuture<Image> loadAndCombineAsync(String name1, String name2) { CompletableFuture<Image> future1 = loadImageAsync(name1); CompletableFuture<Image> future2 = loadImageAsync(name2); return future1.thenCompose(image1 -> future2.thenCompose(image2 -> CompletableFuture.supplyAsync(() -> combineImages(image1, image2)))); } Java
  • 117. CompletableFuture<Image> loadImageAsync(String name) { … } fun loadAndCombineAsync( name1: String, name2: String ): CompletableFuture<Image> = future { val future1 = loadImageAsync(name1) val future2 = loadImageAsync(name2) combineImages(future1.await(), future2.await()) } Kotlin Java
  • 118. CompletableFuture<Image> loadImageAsync(String name) { … } fun loadAndCombineAsync( name1: String, name2: String ): CompletableFuture<Image> = future { val future1 = loadImageAsync(name1) val future2 = loadImageAsync(name2) combineImages(future1.await(), future2.await()) } Kotlin Java
  • 119. CompletableFuture<Image> loadImageAsync(String name) { … } fun loadAndCombineAsync( name1: String, name2: String ): CompletableFuture<Image> = future { val future1 = loadImageAsync(name1) val future2 = loadImageAsync(name2) combineImages(future1.await(), future2.await()) } future coroutine builder Kotlin Java
  • 120. CompletableFuture<Image> loadImageAsync(String name) { … } fun loadAndCombineAsync( name1: String, name2: String ): CompletableFuture<Image> = future { val future1 = loadImageAsync(name1) val future2 = loadImageAsync(name2) combineImages(future1.await(), future2.await()) } Kotlin Java
  • 121. CompletableFuture<Image> loadImageAsync(String name) { … } fun loadAndCombineAsync( name1: String, name2: String ): CompletableFuture<Image> = future { val future1 = loadImageAsync(name1) val future2 = loadImageAsync(name2) combineImages(future1.await(), future2.await()) } Extension for Java’s CompletableFuture Kotlin Java
  • 123. Fibonacci sequence val fibonacci = buildSequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } }
  • 124. val fibonacci = buildSequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } } A coroutine builder with restricted suspension
  • 125. val fibonacci = buildSequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } } A suspending function
  • 126. The same building blocks fun <T> buildSequence( builderAction: suspend SequenceBuilder<T>.() -> Unit ): Sequence<T> { … }
  • 127. fun <T> buildSequence( builderAction: suspend SequenceBuilder<T>.() -> Unit ): Sequence<T> { … } Result is a synchronous sequence
  • 128. fun <T> buildSequence( builderAction: suspend SequenceBuilder<T>.() -> Unit ): Sequence<T> { … } Suspending lambda with receiver
  • 129. fun <T> buildSequence( builderAction: suspend SequenceBuilder<T>.() -> Unit ): Sequence<T> { … } @RestrictsSuspension abstract class SequenceBuilder<in T> { abstract suspend fun yield(value: T) } Coroutine is restricted only to suspending functions defined here
  • 130. Synchronous val fibonacci = buildSequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } } val iter = fibonacci.iterator()
  • 131. val fibonacci = buildSequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } } val iter = fibonacci.iterator() println(iter.next())
  • 132. val fibonacci = buildSequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } } val iter = fibonacci.iterator() println(iter.next())
  • 133. val fibonacci = buildSequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } } val iter = fibonacci.iterator() println(iter.next()) // 1
  • 134. val fibonacci = buildSequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } } val iter = fibonacci.iterator() println(iter.next()) // 1 println(iter.next())
  • 135. val fibonacci = buildSequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } } val iter = fibonacci.iterator() println(iter.next()) // 1 println(iter.next())
  • 136. val fibonacci = buildSequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } } val iter = fibonacci.iterator() println(iter.next()) // 1 println(iter.next()) // 1
  • 137. val fibonacci = buildSequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } } val iter = fibonacci.iterator() println(iter.next()) // 1 println(iter.next()) // 1 println(iter.next()) // 2
  • 138. val fibonacci = buildSequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } } val iter = fibonacci.iterator() println(iter.next()) // 1 println(iter.next()) // 1 println(iter.next()) // 2 Synchronous with invoker
  • 143. Kotlin coroutines Standard library kotlinx-coroutines launch, async, runBlocking, future, delay, Job, Deferred, etc http://github.com/kotlin/kotlinx.coroutines
  • 144. Experimental status Coroutines are here to stay Backwards compatible inside 1.1 & 1.2 To be finalized in the future
  • 145. #kotlinconf17 relizarov elizarov at JetBrains Roman Elizarov Thank you Any questions?