๋ฐ์ํ
์ฝ๋ฃจํด ๋น๋ ํจ์
- ์ฝ๋ฃจํด์ ์์ฑํ๋ ๋ฐ ์ฌ์ฉํ๋ ํจ์ ex) `launch`, `runBlocking`…
- ์ฝ๋ฃจํด์ ๋ง๋ค๊ณ ์ฝ๋ฃจํด์ ์ถ์ํํ Job ๊ฐ์ฒด ์์ฑ → Job ๊ฐ์ฒด๋ก ์ฝ๋ฃจํด์ ์ํ๋ฅผ ์ถ์ ๋ฐ ์ ์ด
Join์ ์ฌ์ฉํ ์ฝ๋ฃจํด ์์ฐจ ์ฒ๋ฆฌ
`join()` : ๋จผ์ ์ฒ๋ฆฌ๋์ด์ผ ํ๋ ์ฝ๋ฃจํด์ ์คํ์ด ์๋ฃ๋ ๋๊น์ง ํธ์ถ๋ถ์ ์ฝ๋ฃจํด์ ์ผ์ ์ค๋จํ๋ ํจ์
๐ก delay ํจ์
- `Thread.sleep()` ํด๋น ํจ์๊ฐ ์คํ๋๋ ๋์ ์ค๋ ๋๊ฐ ๋ธ๋กํน๋ผ ์ฌ์ฉํ ์ ์์
- `delay()` ํด๋น ํจ์๊ฐ ์คํ๋๋ ๋์ ์ค๋ ๋๋ ๋ค๋ฅธ ์ฝ๋ฃจํด์ด ์ฌ์ฉํ ์ ์์
Join ํจ์ ์ฌ์ฉํด ์์ฐจ ์ฒ๋ฆฌํ๊ธฐ
fun main() = runBlocking<Unit> {
val updateTokenJob = launch(Dispatchers.IO) {
println("[${Thread.currentThread().name}] ํ ํฐ ์
๋ฐ์ดํธ ์์")
delay(100L)
println("[${Thread.currentThread().name}] ํ ํฐ ์
๋ฐ์ดํธ ์๋ฃ")
}
updateTokenJob.join()
val networkCallJob = launch(Dispatchers.IO) {
println("[${Thread.currentThread().name}] ๋คํธ์ํฌ ์์ฒญ")
}
}
- `join()` ์ ๋์ ์ฝ๋ฃจํด์ด ์๋ฃ๋ ๋๊น์ง ์ผ์ ์ค๋จ ๋จ → `join()` ์ ์ผ์ ์ค๋จ์ด ๊ฐ๋ฅํ ์ง์ (์ฝ๋ฃจํด ๋ฑ)์์๋ง ํธ์ถ ๊ฐ๋ฅ
JoinAll์ ์ฌ์ฉํ ์ฝ๋ฃจํด ์์ฐจ ์ฒ๋ฆฌ
`joinAll()` ๋ณต์์ ์ฝ๋ฃจํด์ ์คํ์ด ๋ชจ๋ ๋๋ ๋๊น์ง ํธ์ถ๋ถ์ด ์ฝ๋ฃจํด์ ์ผ์ ์ค๋จ
joinAll ํจ์
public suspend fun joinAll(vararg jobs: Job): Unit = jobs.forEach { it.join() }
- ๋ด๋ถ์ ์ผ๋ก forEach ๋ฅผ ์ฌ์ฉํ์ฌ parameter ๋ก ๋ฐ์ Job๋ค์ ๊ฐ๊ฐ join()
joinAll ํจ์ ์ฌ์ฉํด๋ณด๊ธฐ
fun joinAll() = runBlocking<Unit> {
val convertImageJob1: Job = launch(Dispatchers.Default) {
Thread.sleep(1000L) //์ด๋ฏธ์ง ๋ณํ ์์
์คํ ์๊ฐ
println("[${Thread.currentThread().name}] ์ด๋ฏธ์ง1 ๋ณํ ์๋ฃ")
}
val convertImageJob2: Job = launch(Dispatchers.Default) {
Thread.sleep(1000L) //์ด๋ฏธ์ง ๋ณํ ์์
์คํ ์๊ฐ
println("[${Thread.currentThread().name}] ์ด๋ฏธ์ง2 ๋ณํ ์๋ฃ")
}
joinAll(convertImageJob1, convertImageJob2)
val uploadImageJob = launch(Dispatchers.IO) {
println("[${Thread.currentThread().name}] ์ด๋ฏธ์ง1,2 ์
๋ก๋")
}
}
๋ฉ์ธ ์ค๋ ๋ (`runBlocking`) ์ฒ๋ฆฌ ์์
- `Dispatcher.Default` ์ค๋ ๋ ํ์ covertImageJob1 ์คํ ์์ฒญ
- `Dispatcher.Default` ์ค๋ ๋ ํ์ covertImageJob2 ์คํ ์์ฒญ
- `joinAll()`ํธ์ถ → Job1, Job2๊ฐ ์คํ ์๋ฃ๋ ๋๊น์ง ์ผ์ ์ค๋จ
- Job1, Job2๊ฐ ๋ชจ๋ ์๋ฃ๋๋ฉด `runBlocking` ์ฝ๋ฃจํด ์ฌ๊ฒ
CoroutineStart.LAZY ์ฌ์ฉํด ์ฝ๋ฃจํด ์ง์ฐ ์์ํ๊ธฐ
- ์ฝ๋ฃจํด์ ๋จผ์ ์์ฑํด ๋๊ณ ๋์ค์ ์คํํด์ผ ํ๋ ๊ฒฝ์ฐ์ ์ฌ์ฉ
fun coroutineStartLazy() = runBlocking<Unit> {
val startTime = System.currentTimeMillis()
val lazyJob: Job = launch(start = CoroutineStart.LAZY) {
println("[${getElapsedTime(startTime)}] ์ง์ฐ ์คํ")
}
delay(1000L)
lazyJob.start()
}
/*
[์ง๋ ์๊ฐ: 1012ms] ์ง์ฐ ์คํ
*/
- ์์ฑ ํ ์๋์ผ๋ก ์คํ๋์ง ์์ผ๋ฉฐ, `start()` ๋ฅผ ์ฌ์ฉํ์ฌ ์ง์ ์คํ์ ์์ฒญํด์ผ ํจ
์ฝ๋ฃจํด ์ทจ์ํ๊ธฐ
- ์ฝ๋ฃจํด์ด ์คํ๋ ํ์๊ฐ ์์ด์ก์ ๊ฒฝ์ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ ์ ํ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ์ฆ์ ์ทจ์ํด์ผ ํจ
- → ํ์ ์ ์ธ ๋ฆฌ์์ค๋ฅผ ์๋ฏธ ์๋ ์์ ์ ์ฌ์ฉํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ
cancel ์ฌ์ฉํด Job ์ทจ์ํ๊ธฐ
fun cancel() = runBlocking<Unit> {
val startTime = System.currentTimeMillis()
val longJob: Job = launch(Dispatchers.Default) {
repeat(10) { repeatTime ->
delay(1000L)
println("[${getElapsedTime(startTime)}] ๋ฐ๋ณต ํ์ ${repeatTime}")
}
}
delay(3500L)
longJob.cancel()
}
/*
[์ง๋ ์๊ฐ: 1010ms] ๋ฐ๋ณต ํ์ 0
[์ง๋ ์๊ฐ: 2027ms] ๋ฐ๋ณต ํ์ 1
[์ง๋ ์๊ฐ: 3032ms] ๋ฐ๋ณต ํ์ 2
Process finished with exit code 0
*/
`cancel()`
- Job ๊ฐ์ฒด ๋ด๋ถ์ ์ทจ์ ํ์ธ์ฉ ํ๋๊ทธ๋ฅผ ‘์ทจ์ ์์ฒญ๋จ’์ผ๋ก ๋ณ๊ฒฝ → ์ฆ์ ์ทจ์๋๋ ๊ฒ์ ์๋
- ์ดํ ๋ฏธ๋์ ์ด๋ ์์ ์ ์ฝ๋ฃจํด์ ์ทจ์๊ฐ ์์ฒญ๋๋์ง ์ฒดํฌ ํ ์ทจ์
cancelAndJoin์ ์ฌ์ฉํ ์์ฐจ ์ฒ๋ฆฌ
- `cancelAndJoin()` : ์ทจ์์ ๋ํ ์์ฐจ์ฑ์ ๋ณด์ฅ
- ์ฝ๋ฃจํด์ ์ทจ์๊ฐ ์๋ฃ๋ ๋๊น์ง ํธ์ถ๋ถ์ ์ฝ๋ฃจํด์ด ์ผ์ ์ค๋จ
fun cancelAndJoin() = runBlocking<Unit> {
val startTime = System.currentTimeMillis()
val longJob: Job = launch(Dispatchers.Default) {
repeat(10) { repeatTime ->
delay(1000L)
println("[${getElapsedTime(startTime)}] ๋ฐ๋ณต ํ์ ${repeatTime}")
}
}
delay(3500L)
longJob.cancelAndJoin()
println("[${getElapsedTime(startTime)}] ์ทจ์ ํ ์์
")
}
/*
[์ง๋ ์๊ฐ: 1013ms] ๋ฐ๋ณต ํ์ 0
[์ง๋ ์๊ฐ: 2032ms] ๋ฐ๋ณต ํ์ 1
[์ง๋ ์๊ฐ: 3041ms] ๋ฐ๋ณต ํ์ 2
[์ง๋ ์๊ฐ: 3556ms] ์ทจ์ ํ ์์
Process finished with exit code 0
*/
์ฝ๋ฃจํด์ ์ทจ์ ํ์ธ
- `cancel()` , `cancelAndJoin()`
- Job ๊ฐ์ฒด ๋ด๋ถ์ ์๋ ์ทจ์ ํ์ธ์ฉ ํ๋๊ทธ๋ฅผ ๋ฐ๊พธ๋ฉฐ, ์ฝ๋ฃจํด์ด ์ด ํ๋๊ทธ๋ฅผ ํ์ธํ๋ ์์ ์ ๋น๋ก์ ์ทจ์
- ๋ง์ฝ ์ฝ๋ฃจํด์ด ์ทจ์๋ฅผ ํ์ธํ ์ ์๋ ์์ ์ด ์๋ค๋ฉด ์ทจ์๋ ์ผ์ด๋์ง ์์
- while๋ฌธ ๋ด๋ถ์ ์ผ์ ์ค๋จ ์ง์ ์ด ์๊ธฐ ๋๋ฌธ์ ์ผ์ ์ค๋จ์ด ์ผ์ด๋ ์ ์์
fun cancelNotWorking() = runBlocking<Unit> {
val startTime = System.currentTimeMillis()
val whileJob: Job = launch(Dispatchers.Default) {
while (true) {
println("์์
์ค...")
}
}
delay(100L)
whileJob.cancel()
}
/*
์ข
๋ฃ๋์ง ์์!
*/
๐ก ์ผ์ ์ค๋จ ์ง์ , ์ฝ๋ฃจํด์ด ์คํ์ ๋๊ธฐํ๋ ์์ ์ ์ฝ๋ฃจํด์ด ์ทจ์๋ฅผ ํ์ธ
์ฝ๋ฃจํด์ด ์ทจ์ ๋๋๋ก ๋ง๋๋ ๋ฐฉ๋ฒ
- `delay` ๋ฅผ ์ฌ์ฉํ ์ทจ์ ํ์ธ
- `yield` ๋ฅผ ์ฌ์ฉํ ์ทจ์ ํ์ธ
- `CoroutineScope.isActive` ๋ฅผ ์ฌ์ฉํ ์ทจ์ ํ์ธ
delay๋ฅผ ์ฌ์ฉํ ์ทจ์ ํ์ธ
`delay()`
- ์ผ์ ์ค๋จ ํจ์(suspend fun)
- ํน์ ์๊ฐ๋งํผ ํธ์ถ๋ถ์ ์ฝ๋ฃจํด์ ์ผ์ ์ค๋จํ๊ฒ ๋ง๋ฌ
- ๋ถํ์ํ๊ฒ ์์ ์ ์ง์ฐ์์ผ ์ฑ๋ฅ ์ ํ๊ฐ ์ผ์ด๋จ
yield๋ฅผ ์ฌ์ฉํ ์ทจ์ ํ์ธ
`yield()`
- ์์ ์ด ์ฌ์ฉํ๋ ์ค๋ ๋๋ฅผ ์๋ณด
- ์ค๋ ๋ ์ฌ์ฉ์ด ์๋ณด๋๋ฉด์ ์ผ์ ์ค๋จ → ๋นํจ์จ
CoroutineScope.isActive๋ฅผ ์ฌ์ฉํ ์ทจ์ ํ์ธ
- ์ทจ์๊ฐ ์์ฒญ๋๋ฉด `isActive` ํ๋กํผํฐ์ ๊ฐ์ด `false` ๋ก ๋ฐ๋
- ์ค๋ ๋๋ฅผ ์ผ์ ์ค๋จํ๊ฑฐ๋, ์๋ณดํ์ง ์์ผ๋ฉด์ ๊ณ์ ์์ ๊ฐ๋ฅ
์ฝ๋ฃจํด์ ์ํ์ Job์ ์ํ ๋ณ์
- ์์ฑ(New) : ์ฝ๋ฃจํด ๋น๋๋ฅผ ํตํด ์ฝ๋ฃจํด์ ์์ฑํ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ์์ฑ ์ํ์ ๋์ด๋ฉฐ, ์๋์ผ๋ก ์คํ ์ค ์ํ๋ก ๋์ด๊ฐ
- ์คํ์ค(Active): ์ฝ๋ฃจํด์ด ์ค์ ๋ก ์คํ ์ค์ผ ๋๋ฟ๋ง ์๋๋ผ ์คํ๋ ํ์ ์ผ์ ์ค๋จ๋ ์ํ
- ์คํ ์๋ฃ(Completed): ์ฝ๋ฃจํด์ ๋ชจ๋ ์ฝ๋๊ฐ ์คํ ์๋ฃ๋ ์ํ
- ์ทจ์ ์ค(Cancelling): ์ฝ๋ฃจํด์ ์ทจ์๊ฐ ์์ฒญ๋ ์ํ → ์์ง ์ทจ์๊ฐ ๋ ์ํ๋ ์๋๋ฏ๋ก ์ฝ๋ฃจํด์ ๊ณ์ํด์ ์คํ๋จ
- ์ทจ์ ์๋ฃ(Cancelled): ์ฝ๋ฃจํด์ ์ทจ์ ํ์ธ ์์ ์ ์ทจ์๊ฐ ํ์ธ๋ ์ํ → ๋ ์ด์ ์คํ๋์ง ์์
์ฝ๋ฃจํด ์ํ | isActive | isCancelled | isCompleted |
์์ฑ | false | false | false |
์คํ ์ค | true | false | false |
์คํ ์๋ฃ | false | false | true |
์ทจ์ ์ค | false | true | false |
์ทจ์ ์๋ฃ | false | true | true |
http://www.acornpub.co.kr/book/kotlin-coroutines
์ฝํ๋ฆฐ ์ฝ๋ฃจํด์ ์ ์
๋ง์ ๊ฐ๋ฐ์๋ค์ด ์ด๋ ต๊ฒ ๋๋ผ๋ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ๋ค์ํ ์๊ฐ์ ์๋ฃ์ ์ค๋ช ์ ํตํด ๋๊ตฌ๋ ์ฝ๊ฒ ์ดํดํ ์ ์๋๋ก ์ฐ์ธ ์ฑ ์ด๋ค.
www.acornpub.co.kr
๐ํ๊ธฐ๐
Spring Boot - Kotlin ์ฌ์ฉํ๋ ํ๊ฒฝ์์ ์ฝ๋ฃจํด์ ๋ํ ๋ ๊น์ ์ง์์ด ํ์ํด ์ฐพ๋ค ๋ฐ๊ฒฌํ ์ฑ .
ํ๊ตญ์ธ ์ ์ ๋ถ์ด์ด์ ๊ทธ๋ฐ์ง ์ ๋ฐ์ ์ผ๋ก ์ดํดํ๊ธฐ ๊ต์ฅํ ์ฝ๊ฒ ๋์ด์๊ณ ,
๊ธฐ์กด ์ฝํ๋ฆฐ ์ฑ ์์๋ ์ฝ๊ฒ ๋ค๋ค์ง์ง ์๋ ๋ ๋ฅํ ์ฝ๋ฃจํด ๊ธฐ๋ฅ๊น์ง ์ ์ ์์.
(์ง๊ธ๊น์ง ์ฝ์ ๊ธฐ์ ์ ์ค ์ค๋ฌด์์ ๊ฐ์ฅ ์ ์ฐ๊ณ ์๋ ์ฑ ...๊ฐ์ฅ ์ ์ ์ฝํ ์ฑ ...๐)
SpringBoot-Kotlin ํ๊ฒฝ์์ ์ฝ๋ฃจํด์ ๋ ๊ณต๋ถํ๊ณ ์ถ๋ค๋ฉด ์ ๋ง ๊ฐ์ถ ํ์ ํ์ ๐๐ฅ๐๐ฅ๐๐ฅ๐๐ฅ๐๐ฅ
๋ฐ์ํ