1+ package com.sinlov.kotlin.playground.coroutine
2+
3+ import io.kotest.core.spec.style.FunSpec
4+ import io.kotest.matchers.shouldBe
5+ import kotlinx.coroutines.Dispatchers
6+ import kotlinx.coroutines.async
7+ import kotlinx.coroutines.coroutineScope
8+ import kotlinx.coroutines.delay
9+ import kotlinx.coroutines.launch
10+ import kotlinx.coroutines.runBlocking
11+ import kotlinx.coroutines.withContext
12+
13+ /* *
14+ * doc list:
15+ * [Coroutines guide](https://kotlinlang.org/docs/coroutines-guide.html)
16+ * [Coroutines basics](https://kotlinlang.org/docs/coroutines-basics.html)
17+ * [Coroutines and channels − tutorial](https://kotlinlang.org/docs/coroutines-and-channels.html)
18+ */
19+ class CoroutinesBasic : FunSpec ({
20+
21+ test("first coroutine") {
22+ var foo = 0
23+ runBlocking {
24+ launch {
25+ delay(1000L)
26+ println("World !")
27+ foo++
28+ foo shouldBe 1
29+ }
30+ println("Hello ,")
31+ foo shouldBe 0
32+ }
33+ }
34+
35+ test("run suspend") {
36+ var foo = 0
37+ suspend fun doWorld() {
38+ delay(1000L)
39+ foo++
40+ println(", coroutines!!")
41+ foo shouldBe 1
42+ }
43+ async { doWorld() }
44+ foo shouldBe 0
45+ }
46+
47+ test("coroutine context") {
48+ var foo = 0
49+
50+ /* *
51+ * Its function is to create a [coroutineScope], execute the coroutines inside it,
52+ * and exit after all coroutines have been executed.
53+ * The first parameter is the [kotlin.coroutines.CoroutineContext] specified for the coroutine to run.
54+ */
55+ suspend fun doWorld() = coroutineScope { // this: CoroutineScope
56+ launch(Dispatchers .Default ) {
57+ delay(1000L)
58+ foo++
59+ println(", coroutines!!")
60+ foo shouldBe 1
61+ }
62+ println("Hello ")
63+ }
64+ async { doWorld() }
65+ foo shouldBe 0
66+ }
67+
68+ test("coroutine withContext") {
69+ var foo = 0
70+
71+ /* *
72+ * more info see [withContext](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html)
73+ */
74+ suspend fun doWorld() = coroutineScope { // this: CoroutineScope
75+ launch {
76+ withContext(Dispatchers .Default ) {
77+ delay(1000L)
78+ foo++
79+ println(", coroutines!!")
80+ foo shouldBe 1
81+ }
82+ }
83+ println("Hello ")
84+ }
85+ async { doWorld() }
86+ foo shouldBe 0
87+ }
88+
89+ test("concurrently executes both sections") {
90+ var foo = 0
91+
92+ /* *
93+ * We here have pseudo-concurrency;
94+ * we have not specified any threads, and both coroutines are running within the main thread by [Thread.currentThread].
95+ * However, they do not interfere with each other, nor do they cause any blocking.
96+ * They are indeed "running simultaneously."
97+ */
98+ suspend fun doWorld() = coroutineScope { // this: CoroutineScope
99+ launch {
100+ delay(2000L)
101+ foo++
102+ println(", coroutine #2, comes later!")
103+ foo shouldBe 2
104+ }
105+ launch {
106+ delay(1000L)
107+ foo++
108+ println(", coroutine #1, here I am!")
109+ foo shouldBe 1
110+ }
111+ print("Hello ")
112+ }
113+ async { doWorld() }
114+ foo shouldBe 0
115+ }
116+
117+ test("concurrently Controllability ") {
118+ var foo = 0
119+
120+ /* *
121+ * Deferred is a subclass of Job, with the unique feature of obtaining the return result of a coroutine.
122+ * Through its [kotlinx.coroutines.Deferred.await] function, it can "synchronously wait" for the coroutine result to return.
123+ * launch can wait for the coroutine to complete through Job, but cannot obtain the coroutine's return result.
124+ * This is the biggest difference between [launch] and [async].
125+ */
126+ suspend fun doWorld() = coroutineScope {
127+ val job = launch {
128+ delay(2000L)
129+ foo++
130+ println(" and coroutine #2")
131+ foo shouldBe 2
132+ }
133+ launch {
134+ delay(1000L)
135+ foo++
136+ println("from coroutine #1 !")
137+ foo shouldBe 1
138+ }
139+ println("Hello ")
140+ job.join()
141+ println("All jobs done.")
142+ foo shouldBe 2
143+ }
144+
145+ async { doWorld() }
146+ foo shouldBe 0
147+ }
148+ })
0 commit comments