0% found this document useful (0 votes)
10 views89 pages

Kotlin Coroutines-BKUG

Uploaded by

Sjsh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views89 pages

Kotlin Coroutines-BKUG

Uploaded by

Sjsh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 89

Kotlin Coroutines

Asynchronous Programming Made Simple

Kotlin Coroutines | @HeapyHop


Problem

2
Kotlin Coroutines | @HeapyHop
BlogService

3
Kotlin Coroutines | @HeapyHop
AuthenticationService

4
Kotlin Coroutines | @HeapyHop
BlogService - with Threads

Wait AuthenticationService Wait ArticleService

Context Switch Wait UserService Useful work

5
Kotlin Coroutines | @HeapyHop
6
Kotlin Coroutines | @HeapyHop
1M threads?

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread


at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:717)
at kotlin.concurrent.ThreadsKt.thread(Thread.kt:30)
at kotlin.concurrent.ThreadsKt.thread$default(Thread.kt:15)
at by.heap.komodo.samples.coroutines.SuspendKt.main(Suspend.kt:40)

Intel Core i7-6700HQ, 32GB - 10k Thread


7
Kotlin Coroutines | @HeapyHop
Thread Model

8
Kotlin Coroutines | @HeapyHop
Async Model

9
Kotlin Coroutines | @HeapyHop
Use Cases

10
Kotlin Coroutines | @HeapyHop
11
Kotlin Coroutines | @HeapyHop
Microservices/SOA

12
Kotlin Coroutines | @HeapyHop
Android (UIThread)
https://stackoverflow.com/questions/3652560/what-is-the-android-uithr
ead-ui-thread#3653478:

The UIThread is the main thread of execution for your application. This
is where most of your application code is run. All of your application
components (Activities, Services, ContentProviders,
BroadcastReceivers) are created in this thread, and any system calls
to those components are performed in this thread.

13
Kotlin Coroutines | @HeapyHop
14
Kotlin Coroutines | @HeapyHop
How?

15
Kotlin Coroutines | @HeapyHop
Callbacks

16
Kotlin Coroutines | @HeapyHop
AuthenticationService

17
Kotlin Coroutines | @HeapyHop
Callback HELL!

18
Kotlin Coroutines | @HeapyHop
Futures

19
Kotlin Coroutines | @HeapyHop
Futures

20
Kotlin Coroutines | @HeapyHop
CompletableFuture
● compose;
● combine;
● handle;
● accept;
● apply;
● supply.

21
Kotlin Coroutines | @HeapyHop
Coroutines

22
Kotlin Coroutines | @HeapyHop
BlogService

23
Kotlin Coroutines | @HeapyHop
Coroutines

24
Kotlin Coroutines | @HeapyHop
Coroutines

25
Kotlin Coroutines | @HeapyHop
0 callbacks!*
* explicit

26
Kotlin Coroutines | @HeapyHop
Continuation

27
Kotlin Coroutines | @HeapyHop
Coroutines: Hello, World!
compile("org.jetbrains.kotlinx:kotlinx-coroutines-core:0.16")

Error:(56, 5) Kotlin: Suspend function 'delay' should be called only from a coroutine or another
suspend function

28
Kotlin Coroutines | @HeapyHop
Coroutines: Hello, World!

29
Kotlin Coroutines | @HeapyHop
Coroutines: Hello, World!
fun main(args: Array<String>) {
launch(CommonPool) {
delay(1000)
println("Hello, World!")
}
}
// Nothing

30
Kotlin Coroutines | @HeapyHop
Coroutines: Hello, World!
fun main(args: Array<String>) {
launch(CommonPool) {
delay(1000)
println("Hello, World!")
}

Thread.sleep(2000)
}

// Hello, World!

31
Kotlin Coroutines | @HeapyHop
Coroutines: Hello, World!
fun main(args: Array<String>) {
runBlocking {
delay(1000)
print("Hello, ")
}

print("World!")
}

// Hello, World!

32
Kotlin Coroutines | @HeapyHop
Coroutines: Hello, World!

33
Kotlin Coroutines | @HeapyHop
Coroutines + Spring

34
Kotlin Coroutines | @HeapyHop
Suspend functions
Coroutines builders
kotlinx.coroutines

35
Kotlin Coroutines | @HeapyHop
Coroutines & Kotlin
● suspend – language
● low-level core API: coroutine builders, etc – kotlin.coroutines (kotlin-stdlib)
● libraries – example: kotlinx.coroutines (kotlinx-coroutines-core)

36
Kotlin Coroutines | @HeapyHop
Suspend

37
Kotlin Coroutines | @HeapyHop
Suspending Functions
suspend fun delay(
time: Long,
unit: TimeUnit = TimeUnit.MILLISECONDS
) {
// ...
}

38
Kotlin Coroutines | @HeapyHop
Suspending Functions
suspend fun foo() {
delay(1000)
}

39
Kotlin Coroutines | @HeapyHop
Suspending Lambda
public fun launch(
context: CoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {

}

40
Kotlin Coroutines | @HeapyHop
Generators

41
Kotlin Coroutines | @HeapyHop
buildSequence

42
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. buildSequence
public fun <T> buildSequence(
builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> = Sequence { buildIterator(builderAction) }

43
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. buildSequence
val lazySeq: Sequence<Int> = buildSequence {
for (i in 1..100) {
yield(i)
}
}

lazySeq.take(3).forEach { print(it) }
// 123

44
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. buildSequence
val lazySeq: Sequence<Int> = buildSequence {
for (i in 1..100) {
delay(1000)
yield(i)
}
}
Error:(22, 9) Kotlin: Restricted suspending functions can only invoke member or extension suspending
functions on their restricted coroutine scope

public fun <T> buildSequence(


builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> = Sequence { buildIterator(builderAction) }
45
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. SequenceBuilder
@RestrictsSuspension
public abstract class SequenceBuilder<in T> internal constructor() {
public abstract suspend fun yield(value: T)
public abstract suspend fun yieldAll(iterator: Iterator<T>)
...
}

46
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. SequenceBuilder
suspend fun SequenceBuilder<Int>.answer() {
this.yield(42)
}
val ultimateAnswerSeq: Sequence<Int> = buildSequence {
while (true) {
answer()
}
}

47
Kotlin Coroutines | @HeapyHop
buildIterator
Iterator<T>

48
Kotlin Coroutines | @HeapyHop
buildSequence
buildIterator
@RestrictsSuspension

49
Kotlin Coroutines | @HeapyHop
kotlinx.coroutines

50
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. launch

51
Kotlin Coroutines | @HeapyHop
CoroutineContext
● Unconfined
● CommonPool
● newSingleThreadContext, newFixedThreadPoolContext
● Executor.asCoroutineDispatcher

52
Kotlin Coroutines | @HeapyHop
CoroutineStart

53
Kotlin Coroutines | @HeapyHop
CoroutineScope
public interface CoroutineScope {
public val isActive: Boolean
public val context: CoroutineContext
}

54
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. launch

55
Kotlin Coroutines | @HeapyHop
kotlinx.coroutines.experimental. launch

val job = launch(CommonPool) {


while (isActive) {
delay(100)
println(42)
}
}
job.cancel()

56
Kotlin Coroutines | @HeapyHop
kotlinx.coroutines.experimental. NonCancellable

val job = launch(CommonPool) {


try {
// ...
} finally {
run(NonCancellable) {
// this code isn't cancelled
}
}
}
job.cancel()

57
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. async

58
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. async

59
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. yield

60
Kotlin Coroutines | @HeapyHop
kotlinx.coroutines.experimental. (withTimeout/withTimeoutOrNull)

withTimeout(100) {
request.await()
}

withTimeoutOrNull(100) {
request.await()
}

61
Kotlin Coroutines | @HeapyHop
Recursive Coroutines
suspend fun test() {
println(Instant.now())
test()
}

tailrec suspend fun test() {


println(Instant.now())
test()
}

62
Kotlin Coroutines | @HeapyHop
Debug
-Dkotlinx.coroutines.debug

Thread.currentThread().name

[main @coroutine#2]
[main @coroutine#3]
[main @coroutine#1]

public fun newCoroutineContext(context: CoroutineContext):


CoroutineContext = if (DEBUG) context +
CoroutineId(COROUTINE_ID.incrementAndGet()) else context

63
Kotlin Coroutines | @HeapyHop
Call Coroutines from Java
suspend fun foo(): Int {
//...
}

fun fooJava(): CompletableFuture<Int> =


future { foo() }

64
Kotlin Coroutines | @HeapyHop
Not Covered
● Channels
● Select
● ...

65
Kotlin Coroutines | @HeapyHop
Core API

66
Kotlin Coroutines | @HeapyHop
createCoroutine
startCoroutine
suspendCoroutine
suspendCancellableCoroutine

67
Kotlin Coroutines | @HeapyHop
Learn Kotlin Coroutines
● Guide to kotlinx.coroutines by example
● Coroutines for Kotlin
● #coroutines Kotlin Slack
● Андрей Бреслав — Асинхронно, но понятно. Сопрограммы в Kotlin
● Andrey Breslav — Kotlin Coroutines (JVMLS 2016, old coroutines!)
● Корутины в Kotlin - Роман Елизаров, JetBrains

68
Kotlin Coroutines | @HeapyHop
Kotlin Coroutines
Kotlin 1.1: Experimental status.
Kotlin 1.2: ?

// build.gradle
kotlin {
experimental {
coroutines 'enable'
}
}

kotlin.coroutines.experimental -> kotlin.coroutines

69
Kotlin Coroutines | @HeapyHop
Q&A
Ruslan Ibragimov @HeapyHop

Belarus Kotlin User Group: https://bkug.by/

Java Professionals BY: http://jprof.by/

Awesome Kotlin: https://kotlin.link/

Slides: https://goo.gl/5sJXeH

70
Kotlin Coroutines | @HeapyHop
Shared mutable state and concurrency
● Thread-safe data structures (Atomics)
● Thread confinement fine-grained
● Thread confinement coarse-grained
● Mutual exclusion (suspending)
● Actors
● Read more

71
Kotlin Coroutines | @HeapyHop
Core API

72
Kotlin Coroutines | @HeapyHop
createCoroutine

73
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. createCoroutine
public fun <R, T> (suspend R.() -> T).createCoroutine(
receiver: R,
completion: Continuation<T>
): Continuation<Unit> = SafeContinuation(
createCoroutineUnchecked(receiver, completion),
COROUTINE_SUSPENDED
)
block.createCoroutine(receiver, completion)
launch(CommonPool) {
delay(1000)
println("Hello, World!")
}
74
Kotlin Coroutines | @HeapyHop
Bytecode
package by.heap.komodo.samples.coroutines.bytecode

import kotlinx.coroutines.experimental.delay

suspend fun fetch() {


delay(1000)
}

75
Kotlin Coroutines | @HeapyHop
Bytecode
-rw-r--r-- 1 yoda yoda 1342 Jun 1 08:03 ExampleKt.class
-rw-r--r-- 1 yoda yoda 1833 Jun 1 08:03 ExampleKt$fetch$1.class

76
Kotlin Coroutines | @HeapyHop
Bytecode
public final class ExampleKt {
public static final Object fetch(
Continuation<? super Unit>
);
}

77
Kotlin Coroutines | @HeapyHop
Bytecode
public final class ExampleKt {
@Nullable
public static final Object fetch(@NotNull final Continuation<? super
Unit> $continuation) {
Intrinsics.checkParameterIsNotNull((Object)$continuation,
"$continuation");
return new
ExampleKt$fetch.ExampleKt$fetch$1((Continuation)$continuation).doResume((Ob
ject)Unit.INSTANCE, (Throwable)null);
}
}

78
Kotlin Coroutines | @HeapyHop
Bytecode
final class ExampleKt$fetch$1 extends CoroutineImpl {
public final Object doResume(Object, Throwable);
ExampleKt$fetch$1(Continuation);
}

79
Kotlin Coroutines | @HeapyHop
Bytecode
static final class ExampleKt$fetch$1 extends CoroutineImpl {
@Nullable
public final Object doResume(@Nullable final Object data, @Nullable final Throwable throwable) {
final Object coroutine_SUSPENDED = IntrinsicsKt.getCOROUTINE_SUSPENDED();
switch (super.label) {
case 0: {
...
break;
}
case 1: {
...
break;
}
default: {
throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
}
}
return Unit.INSTANCE;
}
}
80
Kotlin Coroutines | @HeapyHop
startCoroutine

81
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. startCoroutine

public fun <R, T> (suspend R.() -> T).startCoroutine(


receiver: R,
completion: Continuation<T>
) {
createCoroutineUnchecked(receiver, completion).resume(Unit)
}

block.startCoroutine(receiver, completion)

82
Kotlin Coroutines | @HeapyHop
suspendCoroutine

83
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. suspendCoroutine

public inline suspend fun <T> suspendCoroutine(


crossinline block: (Continuation<T>) -> Unit
): T = suspendCoroutineOrReturn { c: Continuation<T> ->
val safe = SafeContinuation(c)
block(safe)
safe.getResult()
}

84
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. suspendCoroutine

suspend fun <T> CompletableFuture<T>.await(): T =


suspendCoroutine { cont: Continuation<T> ->
whenComplete { result, exception ->
if (exception == null)
cont.resume(result)
else
cont.resumeWithException(exception)
}
}

85
Kotlin Coroutines | @HeapyHop
suspendCancellableCoroutine

86
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. suspendCancellableCoroutine

public inline suspend fun <T> suspendCancellableCoroutine(


holdCancellability: Boolean = false,
crossinline block: (CancellableContinuation<T>) -> Unit
): T = suspendCoroutineOrReturn { cont ->
val cancellable = CancellableContinuationImpl(cont, active = true)
if (!holdCancellability) cancellable.initCancellability()
block(cancellable)
cancellable.getResult()
}

87
Kotlin Coroutines | @HeapyHop
kotlin.coroutines.experimental. suspendCancellableCoroutine

suspend fun <T> CompletableFuture<T>.await(): T =


suspendCancellableCoroutine { cont: CancellableContinuation<T> ->
whenComplete { result, exception ->
if (exception == null)
cont.resume(result)
else
cont.resumeWithException(exception)
}
cont.invokeOnCompletion { this.cancel(false) }
}

88
Kotlin Coroutines | @HeapyHop
suspend
createCoroutine
startCoroutine
suspendCoroutine
suspendCancellableCoroutine

89
Kotlin Coroutines | @HeapyHop

You might also like