๐ 14.1 ๋์์ฑ๊ณผ ๋ณ๋ ฌ์ฑ
- ๋์์ฑ
- ์ฌ๋ฌ ์์ ์ ๋์์ ์คํํ๋ ๊ฒ
- CPU ์ฝ์ด ํ๋์์ ๋์์ฑ ์ฌ์ฉ ๊ฐ๋ฅ
- ๋ณ๋ ฌ์ฑ
- ์ฝ๋๋ฅผ ์ฌ๋ฌ ๋ถ๋ถ์ผ๋ก ๋๋ ์ ๋์์ ์ํํ ์ ์๋ ๋ฅ๋ ฅ
- ์ฌ๋ฌ CPU ์ฝ์ด์์ ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋์์ ์คํํ๋ ๊ฒ
๐ 14.2 ์ฝํ๋ฆฐ์ ๋์์ฑ ์ฒ๋ฆฌ ๋ฐฉ๋ฒ: ์ผ์ ์ค๋จ ํจ์์ ์ฝ๋ฃจํด
- ์ฝ๋ฃจํด์ ๋น๋๊ธฐ์ ์ผ๋ก ์คํ๋๋ ๋๋ธ๋กํน ๋์์ฑ ์ฝ๋๋ฅผ ์ฐ์ํ๊ฒ ์์ฑํ ์ ์๊ฒ ํด์ค๋ค.
- ์ค๋ ๋์ ๋นํด ๋งค์ฐ ๊ฐ๋ณ๋ค.
- ๋์์ฑ ์์ ๊ณผ ์๋ช ์ฃผ๊ธฐ ๊ด๋ฆฌ ๊ธฐ๋ฅ ์ ๊ณต
๐ 14.3 ์ค๋ ๋์ ์ฝ๋ฃจํด ๋น๊ต
- JVM์์ ๋ณ๋ ฌ ํ๋ก๊ทธ๋๋ฐ๊ณผ ๋์์ฑ ํ๋ก๊ทธ๋๋ฐ์ ์ํ ๊ณ ์ ์ ์ธ ์ถ์ํ๋ ์ค๋ ๋๋ฅผ ์ฌ์ฉํ๋
fun main() {
println("I'm on ${Thread.currentThread().name}")
thread {
println("And I'm on ${Thread.currentThread().name}")
}
}
- ์ค๋ ๋๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ ๋ฐ์์ฑ ์๊ฒ ๋ง๋ค์ด์ฃผ๊ณ , ๋ฉํฐ์ฝ์ด CPU์ ์ฌ๋ฌ ์ฝ์ด์ ์์ ์ ๋ถ์ฐ์์ผ ํ๋์ ์์คํ ์ ๋ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๊ฒ ํด์ค๋ค.
- ์ค๋ ๋ ๊ฐ ์ ํ์ ์ด์์ฒด์ ์ปค๋ ์์ค์์ ์คํ๋๋ ์์
- ์ค๋ ๋๊ฐ ์ด๋ค ์์ ์ด ์๋ฃ๋๊ธธ ๊ธฐ๋ค๋ฆฌ๋ ๋์์๋ ๋ธ๋ก๋๋ค.
- ์ค๋ ๋๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ ๋ฆฝ์ ์ธ ํ๋ก์ธ์ค๋ก ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ์์ ์ ๊ด๋ฆฌํ๊ณ ์กฐ์ ํ๋ ๋ฐ ์ด๋ ค์์ด ์์ ์ ์๋ค.
์ฝํ๋ฆฐ์ ์ค๋ ๋์ ๋ํ ๋์์ผ๋ก ์ฝ๋ฃจํด์ด๋ผ๋ ์ถ์ํ๋ฅผ ๋์
- ์ฝ๋ฃจํด์ ์ด๊ฒฝ๋ ์ถ์ํ๋ค.
- ์ฝ๋ฃจํด์ ์์คํ ์์์ ๋ธ๋ก์ํค์ง ์๊ณ ์คํ์ ์ผ์ ์ค๋จํ ์ ์์ผ๋ฉฐ, ์ค๋จ ์ง์ ์์ ์ฌ๊ฐํ ์ ์๋ค.
- ์ฝ๋ฃจํด์ ๊ตฌ์กฐํ๋ ๋์์ฑ์ด๋ผ๋ ๊ฐ๋ ์ ํตํด ๋์ ์์ ์ ๊ตฌ์กฐ์ ๊ณ์ธต์ ํ๋ฆฝํ๋ฉฐ, ์ทจ์ ๋ฐ ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ์ํ ๋ฉ์ปค๋์ฆ ์ ๊ณต
- ์ฝ๋ฃจํด์ ํ๋ ์ด์์ JVM ์ค๋ ๋์์ ์คํ
๐ 14.4 ์ ์ ๋ฉ์ถ ์ ์๋ ํจ์: ์ผ์ ์ค๋จ ํจ์
- ์ฝํ๋ฆฐ ์ฝ๋ฃจํด์ด ์ค๋ ๋, ๋ฐ์ํ ์คํธ๋ฆผ, ์ฝ๋ฐฑ๊ณผ ๊ฐ์ ๋ค๋ฅธ ๋์์ฑ ์ ๊ทผ ๋ฐฉ์๊ณผ ๋ค๋ฅธ ํต์ฌ ์์ฑ์ผ๋ก๋ ์๋จ์์ ๊ฒฝ์ฐ ์ฝ๋ ํํ๋ฅผ ํฌ๊ฒ ๋ณ๊ฒฝํ ํ์๊ฐ ์๋ค๋ ์ ์ด ์๋ค.
๐ 14.4.1 ์ผ์ ์ค๋จ ํจ์๋ฅผ ์ฌ์ฉํ ์ฝ๋๋ ์์ฐจ์ ์ผ๋ก ๋ณด์ธ๋ค
fun login(credentials: Credentials): UserID
fun loadUserData(userID: UserID): UserData
fun showData(data: UserData)
fun showUserInfo(credentials: Credentials) {
val userID = login(credentials)
val userData = loadUserData(userID)
showData(userData)
}
- ๋ธ๋ก๋ ์ค๋ ๋๋ ์์์ ๋ญ๋น
suspend fun login(credentials: Credentials): UserID
suspend fun loadUserData(userID: UserID): UserData
fun showData(data: UserData)
fun showUserInfo(credentials: Credentials) {
val userID = login(credentials)
val userData = loadUserData(userID)
showData(userData)
}
suspend๋ณ๊ฒฝ์๋ ํจ์๊ฐ ์คํ์ ์ ์ ๋ฉ์ถ ์๋ ์๋ค๋ ๋ป- ex) ๋คํธ์ํฌ ์๋ต์ ๊ธฐ๋ค๋ฆฌ๋ ๊ฒฝ์ฐ ์คํ์ ์ผ์ ์ค๋จ
- ์ผ์ ์ค๋จ์ ๊ธฐ์ ์ค๋ ๋๋ฅผ ๋ธ๋ก์ํค์ง ์๋๋ค.
- ๋ฌผ๋ก
login๊ณผloadUserData์ ๊ตฌํ๋ ์ฝํ๋ฆฐ ์ฝ๋ฃจํด์ ๊ณ ๋ คํด ์์ฑ๋ผ์ผ ํ๋ค.
๐ 14.5 ์ฝ๋ฃจํด์ ๋ค๋ฅธ ์ ๊ทผ ๋ฐฉ๋ฒ๊ณผ ๋น๊ต
fun loginAsync(credentials: Credentials, callback: (UserID) -> Unit) {}
fun loadUserDataAsync(userID: UserID, callback: (UserData) -> Unit) {}
fun showData(data: UserData) {}
fun showUserInfo(credentials: Credentials) {
loginAsync(credentials) { userID ->
loadUserDataAsync(userID) { userData ->
showData(userData)
}
}
}
- ๋ก์ง์ด ์ปค์ง๋ฉด ์ฝ๋ฐฑ์ด ์ค์ฒฉ๋ ์ฝ๋๊ฐ ๋ผ ๊ฐ๋
์ฑ์ด ๊ธ๊ฒฉํ ๋จ์ด์ง๋ค.
- ์ฝ๋ฐฑ ์ง์ฅ
fun loginAsync(credentials: Credentials): CompletableFuture<UserID>
fun loadUserDataAsync(userID: UserID): CompletableFuture<UserData>
fun showData(data: UserData)
fun showUserInfo(credentials: Credentials) {
loginAsync(credentials)
.thenCompose { loadUserDataAsync(it) }
.thenAccept { showData(it) }
}
CompletableFuture์ ์ฌ์ฉํ๋ฉด ์ฝ๋ฐฑ ์ง์ฅ์ ํผํ ์ ์์ง๋ง ์๋ก์ด ์ฐ์ฐ์์ ์๋ฏธ๋ฅผ ๋ฐฐ์์ผ ํ๋ค.- ํจ์์ ๋ฐํ ํ์ ๋ ๋ณ๊ฒฝํด์ผ ํ๋ค.
fun login(credentials: Credentials): Single<UserID>
fun loadUserData(userID: UserID): Single<UserData>
fun showData(data: UserData)
fun showUserInfo(credentials: Credentials) {
login(credentials)
.flatMap { loadUserData(it) }
.doOnSuccess { showData(it) }
.subscribe()
}
- ๋ฐ์ํ ์คํธ๋ฆผ์ ํตํ ๊ตฌํ์ ์ฝ๋ฐฑ ์ง์ฅ์ ํผํ ์ ์์ง๋ง ํจ์ ์๊ทธ๋์ฒ ๋ณ๊ฒฝ ๋ฐ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
์์ ๋น๊ตํด๋ณด๋ฉด ์ฝ๋ฃจํด์ ์ฌ์ฉํ๋ ์ ๊ทผ ๋ฐฉ์์์๋ ํจ์์ suspend ๋ณ๊ฒฝ์๋ง ์ถ๊ฐํ๋ฉด ๋๋ค.
๐ 14.5.1 ์ผ์ ์ค๋จ ํจ์ ํธ์ถ
- ์ผ์ ์ค๋จ ํจ์๋ ์คํ์ ์ผ์ ์ค๋จํ ์ ์๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ ์ฝ๋ ์๋ฌด ๊ณณ์์๋ ํธ์ถํ ์๋ ใ ๋ฒ๋ค.
- ์ผ์ ์ค๋จ ํจ์ ์คํ์ ์ผ์ ์ค๋จํ ์ ์๋ ์ฝ๋ ๋ธ๋ก ์์์๋ง ํธ์ถํ ์ ์๋ค.
- ๊ทธ๋ฐ ๋ธ๋ก ์ค ํ๋๊ฐ ๋ค๋ฅธ ์ผ์ ์ค๋จ ํจ์์ผ ์ ์๋ค.
suspend fun mySuspendingFunction() {}
fun main() {
mySuspendingFunction() // error
}
- ์ผ๋ฐ์ ์ธ ์ผ์ ์ค๋จ ์ฝ๋๊ฐ ์๋ ์ฝ๋์์ ์ผ์ ์ค๋จ ํจ์๋ฅผ ํธ์ถํ๋ ค๊ณ ํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์
- main ํจ์๋ฅผ
suspend๋ก ํ๋ฉด ํธ์ถ ๊ฐ๋ฅ
๐ 14.6 ์ฝ๋ฃจํด ์ธ๊ณ๋ก ๋ค์ด๊ฐ๊ธฐ: ์ฝ๋ฃจํด ๋น๋
- ์ฝ๋ฃจํด์ ์ผ์ ์ค๋จ ๊ฐ๋ฅํ ๊ณ์ฐ์ ์ธ์คํด์ค๋ค.
- ๋ค๋ฅธ ์ฝ๋ฃจํด๋ค๊ณผ ๋์์ ์คํ๋ ์ ์๋ ์ฝ๋ ๋ธ๋ก
- ์ค๋ ๋์ ๋น์ทํ์ง๋ง ์ฝ๋ฃจํด์ ํจ์ ์คํ์ ์ผ์ ์ค๋จํ๋ ๋ฐ ํ์ํ ๋ฉ์ปค๋์ฆ์ ํฌํจํ๊ณ ์๋ค.
runBlocking์ ๋ธ๋กํน ์ฝ๋์ ์ผ์ ์ค๋จ ํจ์์ ์ธ๊ณ๋ฅผ ์ฐ๊ฒฐํ ๋ ์ฐ์ธ๋ค.launch๋ ๊ฐ์ ๋ฐํํ์ง ์๋ ์๋ก์ด ์ฝ๋ฃจํด์ ์์ํ ๋ ์ฐ์ธ๋ค.async๋ ๋น๋๊ธฐ์ ์ผ๋ก ๊ฐ์ ๊ณ์ฐํ ๋ ์ฐ์ธ๋ค.
๐ 14.6.1 ์ผ๋ฐ ์ฝ๋์์ ์ฝ๋ฃจํด์ ์ธ๊ณ๋ก: runBlocking
suspend fun doSomethingSlowly() {
delay(500.milliseconds)
println("I'm done")
}
fun main() = runBlocking {
doSomethingSlowly()
}
- ์ ์ฝ๋ฃจํด์ ์์ฑํ๊ณ ์คํํ๋ฉฐ, ํด๋น ์ฝ๋ฃจํด์ด ์๋ฃ๋ ๋๊น์ง ํ์ฌ ์ค๋ ๋๋ฅผ ๋ธ๋ก์ํจ๋ค.
runBlocking์ ์ฌ์ฉํ ๋๋ ํ๋์ ์ค๋ ๋๋ฅผ ๋ธ๋กํนํ๋ค.- ๋ค๋ง, ์ถ๊ฐ์ ์ธ ์์ ์ฝ๋ฃจํด์ ์ผ๋ง๋ ์ง ์์ํ ์ ์๊ณ , ์ด๋ค์ ๋ค๋ฅธ ์ค๋ ๋๋ฅผ ๋ ์ด์ ๋ธ๋ก์ํค์ง ์๋๋ค.
๐ 14.6.2 ๋ฐ์ฌ ํ ๋ง๊ฐ ์ฝ๋ฃจํด ์์ฑ: launch ํจ์
private var zeroTime = System.currentTimeMillis()
fun log(message: Any?) =
println("${System.currentTimeMillis() - zeroTime} " + "[${Thread.currentThread().name}] $message")
fun main() = runBlocking {
log("The first, parent, coroutine starts")
launch {
log("The second coroutine starts and is ready to be suspended")
delay(100.milliseconds)
log("The second coroutine is resumed")
}
launch {
log("The third coroutine can run in the meantime")
}
log("The first coroutine has launched two more coroutines")
}
- ์ด ์์ ๋ฅผ ์คํํ๋ฉด ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ๋๋ค.
-Dkotlinx.coroutines.debugJVM ์ต์ ํฌํจ ์คํ
38 [main @coroutine#1] The first, parent, coroutine starts
52 [main @coroutine#1] The first coroutine has launched two more coroutines
53 [main @coroutine#2] The second coroutine starts and is ready to be suspended
58 [main @coroutine#3] The third coroutine can run in the meantime
163 [main @coroutine#2] The second coroutine is resumed
- ๋ณ๋ ฌ์ฑ ์์ด ๊ต์ฐจ ์คํ๋๋ ๊ฒฝ์ฐ๋ค. ์ฆ, ๋ชจ๋ ์ฝ๋ฃจํด์ด ๊ฐ์ ์ค๋ ๋์์ ์คํ
launch๋ฅผ ์ฌ์ฉํด ์๋ก์ด ๊ธฐ๋ณธ ์ฝ๋ฃจํด์ ์์ํ ์ ์๋ค.
๐ 14.6.3 ๋๊ธฐ ๊ฐ๋ฅํ ์ฐ์ฐ: async ๋น๋
suspend fun slowlyAddNumbers(a: Int, b: Int): Int {
log("Waiting a bit before calculating $a + $b")
delay(100.milliseconds * a)
return a + b
}
fun main() = runBlocking {
log("Starting the async computation")
val myFirstDeferred = async { slowlyAddNumbers(2, 2) }
val mySecondDeferred = async { slowlyAddNumbers(4, 4) }
log("Waiting for the deferred value to be available")
log("The first result: ${myFirstDeferred.await()}")
log("The second result: ${mySecondDeferred.await()}")
}
- ์ด ์์ ๋ฅผ ์คํํ๋ฉด ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ๋๋ค.
44 [main @coroutine#1] Starting the async computation
60 [main @coroutine#1] Waiting for the deferred value to be available
65 [main @coroutine#2] Waiting a bit before calculating 2 + 2
71 [main @coroutine#3] Waiting a bit before calculating 4 + 4
287 [main @coroutine#1] The first result: 4
481 [main @coroutine#1] The second result: 8
async๋ฅผ ํธ์ถํ ๋๋ง๋ค ์๋ก์ด ์ฝ๋ฃจํด์ ์์ํจ์ผ๋ก์จ ๋ ๊ณ์ฐ์ด ๋์์ ์ผ์ด๋๊ฒ ํ๋ค.await๋ฅผ ํธ์ถํ๋ฉด ๊ทธDeferred์์ ๊ฒฐ๊ด๊ฐ์ด ์ฌ์ฉ ๊ฐ๋ฅํด์ง ๋๊น์ง ๋ฃจํธ ์ฝ๋ฃจํด์ด ์ผ์ ์ค๋จ๋๋ค.Deferred๊ฐ์ฒด๋ ์์ง ์ฌ์ฉํ ์ ์๋ ๊ฐ์ ๋ํ๋ธ๋ค.- ๋งค๋์ ์ธ์ ๊ฐ๋ ๊ฐ์ ์๊ฒ ๋ ๊ฒ์ด๋ผ๋ ์ฝ์, ์ฐ๊ธฐ๋ ๊ณ์ฐ ๊ฒฐ๊ด๊ฐ์ ๋ํ๋ธ๋ค.
| ๋น๋ | ๋ฐํ๊ฐ | ์ฐ์์ |
|---|---|---|
runBlocking |
๋๋ค๊ฐ ๊ณ์ฐํ ๊ฐ | ๋ธ๋กํน ์ฝ๋์ ๋๋ธ๋กํน ์ฝ๋ ์ฌ์ด๋ฅผ ์ฐ๊ฒฐ |
launch |
Job |
๋ฐ์ฌ ํ ๋ง๊ฐ ์ฝ๋ฃจํด ์์(๋ถ์ ํจ๊ณผ๊ฐ ์์) |
async |
Deferred<T> |
๊ฐ์ ๋น๋๊ธฐ๋ก ๊ณ์ฐ(๊ฐ์ ๊ธฐ๋ค๋ฆด ์ ์์) |
๐ 14.7 ์ด๋์ ์ฝ๋๋ฅผ ์คํํ ์ง ์ ํ๊ธฐ: ๋์คํจ์ฒ
- ์ฝ๋ฃจํด์ ๋์คํจ์ฒ๋ ์ฝ๋ฃจํด์ ์คํํ ์ค๋ ๋๋ฅผ ๊ฒฐ์
- ๋์คํจ์ฒ๋ฅผ ์ ํํจ์ผ๋ก์จ ์ฝ๋ฃจํด์ ํน์ ์ค๋ ๋๋ก ์ ํํ๊ฑฐ๋ ์ค๋ ๋ ํ์ ๋ถ์ฐ์ํฌ ์ ์์ผ๋ฉฐ, ์ฝ๋ฃจํด์ด ํ ์ค๋ ๋์์๋ง ์คํ๋ ์ง ์ฌ๋ฌ ์ค๋ ๋์์ ์คํ๋ ์ง ๊ฒฐ์ ํ ์ ์๋ค.
๐ 14.7.1 ๋์คํจ์ฒ ์ ํ
- ์ฝ๋ฃจํด์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ถ๋ชจ ์ฝ๋ฃจํด์์ ๋์คํจ์ฒ๋ฅผ ์์๋ฐ์ผ๋ฏ๋ก ๋ชจ๋ ์ฝ๋ฃจํด์ ๋ํด ๋ช ์์ ์ผ๋ก ๋์คํจ์ฒ๋ฅผ ์ง์ ํ ํ์๋ ์๋ค.
๐ ๏ธ ๋ค์ค ์ค๋ ๋๋ฅผ ์ฌ์ฉํ๋ ๋ฒ์ฉ ๋์คํจ์ฒ: Dispatchers.Default
- ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๋์คํจ์ฒ
- CPU ์ฝ์ด ์๋งํผ์ ์ค๋ ๋๋ก ๊ตฌ์ฑ๋ ์ค๋ ๋ ํ์ ๊ธฐ๋ฐ์ผ๋ก ํจ
- ์ฌ๋ฌ ์ค๋ ๋์์ ์ฝ๋ฃจํด์ด ๋ถ์ฐ๋ผ ์คํ
๐ ๏ธ UI ์ค๋ ๋์์ ์คํ: Dispatchers.Main
- UI ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ ๋๋ ํน์ ์์ ์ UI ์ค๋ ๋๋ ๋ฉ์ธ ์ค๋ ๋๋ผ๊ณ ๋ถ๋ฆฌ๋ ํน์ ์ค๋ ๋์์ ์คํํด์ผ ๋ ๋๊ฐ ์๋ค.
Dispatchers.Main์ ์ค์ ๊ฐ์ ์ฌ์ฉํ๋ ํ๋ ์์ํฌ์ ๋ฐ๋ผ ๋ค๋ฅด๋ค.
๐ ๏ธ ๋ธ๋กํน๋๋ IO ์์ ์ฒ๋ฆฌ: Dispatchers.IO
- ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๋ ์ฝ๋ฃจํด์ ์ผ๋์ ๋๊ณ ์ค๊ณ๋ API๋ฅผ ์ ํํ ์ ์๋ ๊ฒฝ์ฐ
Dispatchers.IO์์ ์คํ๋ ์ฝ๋ฃจํด์ ์๋์ผ๋ก ํ์ฅ๋๋ ์ค๋ ๋ ํ์์ ์คํ- CPU ์ง์ฝ์ ์ด์ง ์์ ์์ (๋ธ๋กํน API ์๋ต ๋๊ธฐ)์ ์ ํฉ
| ๋์คํจ์ฒ | ์ค๋ ๋ ๊ฐ์ | ์ฐ์์ |
|---|---|---|
Dispatchers.Default |
CPU ์ฝ์ด ์ | ์ผ๋ฐ์ ์ธ ์ฐ์ฐ, CPU ์ง์ฝ์ ์ธ ์์ |
Dispatchers.Main |
1 | UI ํ๋ ์์ํฌ์ ๋งฅ๋ฝ์์๋ง ์์ |
Dispatchers.IO |
64 + CPU ์ฝ์ด ๊ฐ์(๋จ, ์ต๋ 64๊ฐ๋ง ๋ณ๋ ฌ ์คํ) | ๋ธ๋กํน IO ์์ , ๋คํธ์ํฌ ์์ , ํ์ผ ์์ |
Dispatchers.Unconfined |
์๋ฌด ์ค๋ ๋๋ | ์ฆ์ ์ค์ผ์ค๋งํด์ผ ํ๋ ํน๋ณํ ๊ฒฝ์ฐ |
limitedParallelism(n) |
์ปค์คํ (n) | ์ปค์คํ ์๋๋ฆฌ์ค |
๐ 14.7.2 ์ฝ๋ฃจํด ๋น๋์ ๋์คํจ์ฒ ์ ๋ฌ
fun main() {
runBlocking {
log("Doing some work")
launch(Dispatchers.Default) {
log("Doing some background work")
}
}
}
- ์ฝ๋ฃจํด ๋น๋ ํจ์๋ ์ฝ๋ฃจํด ๋์คํจ์ฒ๋ฅผ ๋ช ์์ ์ผ๋ก ์ง์ ํ ์ ์๊ฒ ํ๋ค.
- ์ ์ฝ๋์ ์คํ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค.
45 [main @coroutine#1] Doing some work
63 [DefaultDispatcher-worker-2 @coroutine#2] Doing some background work
๐ 14.7.3 withContext๋ฅผ ์ฌ์ฉํด ์ฝ๋ฃจํด ์์์ ๋์คํจ์ฒ ๋ฐ๊พธ๊ธฐ
launch(Dispatchers.Default) {
val result = performBackgroundOperation()
withContext(Dispatchers.Main) {
updateUI(result)
}
}
- ์ด๋ฏธ ์คํ ์ค์ธ ์ฝ๋ฃจํด์์ ๋์คํจ์ฒ๋ฅผ ๋ฐ๊ฟ ๋๋
withContextํจ์์ ๋ค๋ฅธ ๋์คํจ์ฒ๋ฅผ ์ ๋ฌ
๐ 14.7.4 ์ฝ๋ฃจํด๊ณผ ๋์คํจ์ฒ๋ ์ค๋ ๋ ์์ ์ฑ ๋ฌธ์ ์ ๋ํ ๋ง๋ฒ ๊ฐ์ ํด๊ฒฐ์ฑ ์ด ์๋๋ค
fun main() {
runBlocking {
launch(Dispatchers.Default) {
var x = 0
repeat(10_000) {
x++
}
println(x)
}
}
}
- ์ฝ๋ฃจํด์ด ์ข ๋ฃ๋ ํ x ๊ฐ์ 10000์ผ๋ก ์ ํํ๋ค.
- ํ ์ฝ๋ฃจํด์ด ์์์ ์ค๋ ๋์์ ์คํ๋๋๋ผ๋ ๊ทธ ๋ก์ง์ด ์๊ฒฉํ๊ฒ ์์ฐจ์ ์ผ๋ก ์คํ๋๊ธฐ ๋๋ฌธ
fun main() {
runBlocking {
var x = 0
repeat(10_000) {
launch(Dispatchers.Default) {
x++
}
}
delay(1.seconds)
println(x)
}
}
- ์นด์ดํฐ ๊ฐ์ด ์์๋ณด๋ค ๋ฎ๋ค.
- ์ฌ๋ฌ ์ฝ๋ฃจํด์ด ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ณ ์๊ธฐ ๋๋ฌธ
fun main() = runBlocking {
val mutex = Mutex()
var x = 0
repeat(10_000) {
launch(Dispatchers.Default) {
mutex.withLock {
x++
}
}
}
delay(1.seconds)
println(x)
}
Mutex์ ๊ธ์ ํตํด ์ฝ๋ ์๊ณ ์์ญ์ด ํ ๋ฒ์ ํ๋์ ์ฝ๋ฃจํด๋ง ์คํ๋๊ฒ ๋ณด์ฅํ ์ ์๋ค.
๐ 14.8 ์ฝ๋ฃจํด์ ์ฝ๋ฃจํด ์ฝํ ์คํธ์ ์ถ๊ฐ์ ์ธ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋ค
- ๊ฐ ์ฝ๋ฃจํด์ ์ถ๊ฐ์ ์ธ ๋ฌธ๋งฅ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋๋ฐ, ์ด ๋ฌธ๋งฅ์
CoroutineContext๋ผ๋ ํํ๋ก ์ ๊ณต CoroutineContext๋ ์ฌ๋ฌ ์์๋ก ์ด๋ค์ง ์งํฉ- ์ด ์์ ์ค ํ๋๋ ์ฝ๋ฃจํด์ด ์ด๋ค ์ค๋ ๋์์ ์คํ๋ ์ง๋ฅผ ๊ฒฐ์ ํ๋ ๋์คํจ์ฒ
CoroutineContext์๋ ์ฝ๋ฃจํด์ ์๋ช ์ฃผ๊ธฐ์ ์ทจ์๋ฅผ ๊ด๋ฆฌํ๋Job๊ฐ์ฒด ํฌํจCoroutineContext์๋CoroutineNmae,CoroutineExceptionHandler์ ๊ฐ์ ๋ฉํ๋ฐ์ดํฐ๋ ํฌํจ
suspend fun introspect() {
log(coroutineContext)
}
fun main() {
runBlocking {
introspect()
}
}
- ์ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค.
39 [main @coroutine#1] [CoroutineId(1), "coroutine#1":BlockingCoroutine{Active}@32709393, BlockingEventLoop@3d99d22e]
fun main() {
runBlocking(Dispatchers.IO + CoroutineName("Coolroutine")) {
introspect()
}
}
- ์ฝ๋ฃจํด ๋น๋์ ์ธ์๋ฅผ ์ ๋ฌํ๋ฉด ์์ ์ฝ๋ฃจํด์ ์ฝํ ์คํธ์์ ํด๋น ์์๋ฅผ ๋ฎ์ด์ด๋ค.
43 [DefaultDispatcher-worker-1 @Coolroutine#1] [CoroutineName(Coolroutine), CoroutineId(1), "Coolroutine#1":BlockingCoroutine{Active}@1be729a6, Dispatchers.IO]
