KEMBAR78
Fresh Async with Kotlin | PDF
Fresh	Async	With	Kotlin
Presented	at	QCon SF,	2017
/Roman	Elizarov	@	JetBrains
InfoQ.com: News & Community Site
• Over 1,000,000 software developers, architects and CTOs read the site world-
wide every month
• 250,000 senior developers subscribe to our weekly newsletter
• Published in 4 languages (English, Chinese, Japanese and Brazilian
Portuguese)
• Post content from our QCon conferences
• 2 dedicated podcast channels: The InfoQ Podcast, with a focus on
Architecture and The Engineering Culture Podcast, with a focus on building
• 96 deep dives on innovative topics packed as downloadable emags and
minibooks
• Over 40 new content items per week
Watch the video with slide
synchronization on InfoQ.com!
https://www.infoq.com/presentations/
kotlin-async
Purpose of QCon
- to empower software development by facilitating the spread of
knowledge and innovation
Strategy
- practitioner-driven conference designed for YOU: influencers of
change and innovation in your teams
- speakers and topics driving the evolution and innovation
- connecting and catalyzing the influencers and innovators
Highlights
- attended by more than 12,000 delegates since 2007
- held in 9 cities worldwide
Presented at QCon San Francisco
www.qconsf.com
Speaker:	Roman	Elizarov
• 16+	years	experience
• Previously	developed	high-perf	trading	software	
@	Devexperts
• Teach	concurrent	&	distributed	programming	
@	St.	Petersburg	ITMO	University
• Chief	judge	
@	Northern	Eurasia	Contest	/	ACM	ICPC	
• Now	team	lead	in	Kotlin	Libraries	
@	JetBrains
Pragmatic.	Concise.	Modern.	Interoperable	with	Java.
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
Kotlin
2
fun requestToken(): Token { … }
fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) {
// does some local processing of result
}
A	toy	problem
Kotlin
3
fun requestToken(): Token { … }
fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
A	toy	problem
Kotlin
fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
1
2
3
Can	be	done	with	threads!
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
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
natural	signature
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())
}
• Custom	higher-order	functions
Bonus	features
val post = retryIO {
createPost(token, item)
}
Everything	like	in	blocking	code
How	does	it	work?
A	quick	peek	behind	the	scenes
Kotlin	suspending	functions
callback
Kotlin
Java/JVM
suspend fun createPost(token: Token, item: Item): Post { … }
Object createPost(Token token, Item item, Continuation<Post> cont) { … }
Kotlin	suspending	functions
callback
Kotlin
Java/JVM
Continuation	is	a	generic	callback	interface
suspend fun createPost(token: Token, item: Item): Post { … }
Object createPost(Token token, Item item, Continuation<Post> cont) { … }
interface Continuation<in T> {
val context: CoroutineContext
fun resume(value: T)
fun resumeWithException(exception: Throwable)
}
Kotlin	suspending	functions
callback
Kotlin
Java/JVM
suspend fun createPost(token: Token, item: Item): Post { … }
Object createPost(Token token, Item item, Continuation<Post> cont) { … }
interface Continuation<in T> {
val context: CoroutineContext
fun resume(value: T)
fun resumeWithException(exception: Throwable)
}
Kotlin	suspending	functions
callback
Kotlin
Java/JVM
suspend fun createPost(token: Token, item: Item): Post { … }
Object createPost(Token token, Item item, Continuation<Post> cont) { … }
interface Continuation<in T> {
val context: CoroutineContext
fun resume(value: T)
fun resumeWithException(exception: Throwable)
}
Kotlin	suspending	functions
callback
Kotlin
Java/JVM
suspend fun createPost(token: Token, item: Item): Post { … }
Object createPost(Token token, Item item, Continuation<Post> cont) { … }
interface Continuation<in T> {
val context: CoroutineContext
fun resume(value: T)
fun resumeWithException(exception: Throwable)
}
Code	with	suspension	points
Kotlin
Java/JVM
Compiles	to	state	machine	
(simplified	code	shown)
val token = requestToken()
val post = createPost(token, item)
processPost(post)
switch (cont.label) {
case 0:
cont.label = 1;
requestToken(cont);
break;
case 1:
Token token = (Token) prevResult;
cont.label = 2;
createPost(token, item, cont);
break;
case 2:
Post post = (Post) prevResult;
processPost(post);
break;
}
Code	with	suspension	points
Kotlin
Java/JVM
val token = requestToken()
val post = createPost(token, item)
processPost(post)
switch (cont.label) {
case 0:
cont.label = 1;
requestToken(cont);
break;
case 1:
Token token = (Token) prevResult;
cont.label = 2;
createPost(token, item, cont);
break;
case 2:
Post post = (Post) prevResult;
processPost(post);
break;
}
Integration
Zoo	of	futures	on	JVM
interface Service {
fun createPost(token: Token, item: Item): Call<Post>
}
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
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
suspend fun <T> Call<T>.await(): T {
…
}
Callbacks	everywhere
suspend fun <T> Call<T>.await(): T {
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
// todo
}
override fun onFailure(call: Call<T>, t: Throwable) {
// todo
}
})
}
suspend fun <T> Call<T>.await(): T = suspendCoroutine { cont ->
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
if (response.isSuccessful)
cont.resume(response.body()!!)
else
cont.resumeWithException(ErrorResponse(response))
}
override fun onFailure(call: Call<T>, t: Throwable) {
cont.resumeWithException(t)
}
})
}
suspend fun <T> suspendCoroutine(block: (Continuation<T>) -> Unit): T
suspend fun <T> suspendCoroutine(block: (Continuation<T>) -> Unit): T
suspend fun <T> suspendCoroutine(block: (Continuation<T>) -> Unit): T
Regular	function
Inspired	by	call/cc from	Scheme
suspend fun <T> Call<T>.await(): T = suspendCoroutine { cont ->
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
if (response.isSuccessful)
cont.resume(response.body()!!)
else
cont.resumeWithException(ErrorResponse(response))
}
override fun onFailure(call: Call<T>, t: Throwable) {
cont.resumeWithException(t)
}
})
}
Install	callback
suspend fun <T> Call<T>.await(): T = suspendCoroutine { cont ->
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
if (response.isSuccessful)
cont.resume(response.body()!!)
else
cont.resumeWithException(ErrorResponse(response))
}
override fun onFailure(call: Call<T>, t: Throwable) {
cont.resumeWithException(t)
}
})
}
Install	callback
suspend fun <T> Call<T>.await(): T = suspendCoroutine { cont ->
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
if (response.isSuccessful)
cont.resume(response.body()!!)
else
cont.resumeWithException(ErrorResponse(response))
}
override fun onFailure(call: Call<T>, t: Throwable) {
cont.resumeWithException(t)
}
})
}
Analyze	response
suspend fun <T> Call<T>.await(): T = suspendCoroutine { cont ->
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
if (response.isSuccessful)
cont.resume(response.body()!!)
else
cont.resumeWithException(ErrorResponse(response))
}
override fun onFailure(call: Call<T>, t: Throwable) {
cont.resumeWithException(t)
}
})
}
Analyze	response
suspend fun <T> Call<T>.await(): T = suspendCoroutine { cont ->
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
if (response.isSuccessful)
cont.resume(response.body()!!)
else
cont.resumeWithException(ErrorResponse(response))
}
override fun onFailure(call: Call<T>, t: Throwable) {
cont.resumeWithException(t)
}
})
}
That’s	all
Out-of-the	box	integrations
kotlinx-coroutines-core
jdk8
guava
nio
reactor
rx1
rx2
Coroutine	builders
How	can	we	start	a	coroutine?
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 execution	A	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 execution	A	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
The	classic	approach
Kotlin-way
suspend fun postItem(item: Item) {
val token = requestToken()
val post = createPost(token, item)
processPost(post)
}
suspend fun requestToken(): Token { … }
suspend fun createPost(token: Token, item: Item): Post { … }
fun processPost(post: Post) { … }
Kotlin
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)
async Task<Token> requestToken() { … }
async Task<Post> createPost(Token token, Item item) { … }
void processPost(Post post) { … }
C#
async Task postItem(Item item) {
var token = await requestToken();
var post = await createPost(token, item);
processPost(post);
}
Classic-way
mark	with	async
async Task<Token> requestToken() { … }
async Task<Post> createPost(Token token, Item item) { … }
void processPost(Post post) { … }
C#
async Task postItem(Item item) {
var token = await requestToken();
var post = await createPost(token, item);
processPost(post);
}
Classic-way
use	await	to	suspend
async Task<Token> requestToken() { … }
async Task<Post> createPost(Token token, Item item) { … }
void processPost(Post post) { … }
C#
async Task postItem(Item item) {
var token = await requestToken();
var post = await createPost(token, item);
processPost(post);
}
Classic-way
returns	a	future
async Task<Token> requestToken() { … }
async Task<Post> createPost(Token token, Item item) { … }
void processPost(Post post) { … }
C#
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
Concurrency	is	hard
Concurrency	has	to	be	explicit
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);
var promise1 = loadImageAsync(name1);
var promise2 = loadImageAsync(name2);
var image1 = await promise1;
var image2 = await promise2;
async Task<Image> loadImageAsync(String name) { … }C#
Kotlin	async function
fun loadImageAsync(name: String): Deferred<Image> =
async { … }
Kotlin
Kotlin	async function
fun loadImageAsync(name: String): Deferred<Image> =
async { … }
A	regular	function
Kotlin
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
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
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
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
Can	we	use	Kotlin	coroutines	with	Java	code?
Java	interop
CompletableFuture<Image> loadImageAsync(String name) { … }Java
CompletableFuture<Image> loadImageAsync(String name) { … }
CompletableFuture<Image> loadAndCombineAsync(String name1,
String name2)
Java
Imagine	implementing	it	in	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) { … }Java
fun loadAndCombineAsync(
name1: String,
name2: String
): CompletableFuture<Image> =
…
Kotlin
CompletableFuture<Image> loadImageAsync(String name) { … }Java
fun loadAndCombineAsync(
name1: String,
name2: String
): CompletableFuture<Image> =
future {
val future1 = loadImageAsync(name1)
val future2 = loadImageAsync(name2)
combineImages(future1.await(), future2.await())
}
Kotlin
CompletableFuture<Image> loadImageAsync(String name) { … }Java
fun loadAndCombineAsync(
name1: String,
name2: String
): CompletableFuture<Image> =
future {
val future1 = loadImageAsync(name1)
val future2 = loadImageAsync(name2)
combineImages(future1.await(), future2.await())
}
Kotlin
future	coroutine	builder
CompletableFuture<Image> loadImageAsync(String name) { … }Java
fun loadAndCombineAsync(
name1: String,
name2: String
): CompletableFuture<Image> =
future {
val future1 = loadImageAsync(name1)
val future2 = loadImageAsync(name2)
combineImages(future1.await(), future2.await())
}
Kotlin
CompletableFuture<Image> loadImageAsync(String name) { … }Java
fun loadAndCombineAsync(
name1: String,
name2: String
): CompletableFuture<Image> =
future {
val future1 = loadImageAsync(name1)
val future2 = loadImageAsync(name2)
combineImages(future1.await(), future2.await())
}
Kotlin
Beyond	asynchronous	code
Kotlin’s approach	to	generate/yield	– synchronous	coroutines
Fibonacci	sequence
val fibonacci: Sequence<Int> = …
Fibonacci	sequence
val fibonacci = buildSequence {
var cur = 1
var next = 1
while (true) {
yield(cur)
val tmp = cur + next
cur = next
next = tmp
}
}
Fibonacci	sequence
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
Fibonacci	sequence
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
public fun <T> buildSequence(
builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> { … }
The	same	building	blocks
public fun <T> buildSequence(
builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> { … }
Result	is	a	synchronous sequence
The	same	building	blocks
public fun <T> buildSequence(
builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> { … }
Suspending	lambda	with	receiver
The	same	building	blocks
public 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
Library	vs	Language
Keeping	the	core	language	small
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	in	Kotlin	1.1	&	1.2
Coroutines	can	be	used in	production
Backwards	compatible	inside	1.1	&	1.2
To	be	finalized	in	the	future
Thank	you
Any	questions?
Slides	are	available	at	www.slideshare.net/elizarov
email	me	to	elizarov at	gmail
relizarov
Watch the video with slide
synchronization on InfoQ.com!
https://www.infoq.com/presentations/
kotlin-async

Fresh Async with Kotlin