π‘ μ½λ£¨ν΄μμ μ€λ¨μ΄ μ΄λ»κ² λμνλμ§ νμ΅νμμ΅λλ€.
μ€λ¨μ μ΄λ»κ² μλν κΉ?
- μ€λ¨ ν¨μλ μ½νλ¦° μ½λ£¨ν΄μ ν΅μ¬μ΄ λ©λλ€.
- μ½λ£¨ν΄μ μ€λ¨νλ€λ κ²μ μ€νμ μ€κ°μ λ©μΆλ κ²μ μλ―Έν©λλ€.
- 체ν¬ν¬μΈνΈμ κ²μμ μ μ₯νκ³ λ€λ₯Έ κ²μμ λμνλ κ²κ³Ό κ°μΌλ©°, μ¬μ©μμ μ»΄ν¨ν°λ κ°κ° λ€λ₯Έ μΌμ μ§μ€ν μ μμ΅λλ€.
- κ²μμ μ¬κ°ν κ²½μ° μ μ₯ν 체ν¬ν¬μΈν°μμ μ€ννλ€λ©΄ μ΄μ μ μ’ λ£νλ μκ°λΆν° κ²μμ μ¦κΈΈ μ μμ΅λλ€.
- μ½λ£¨ν΄μ μ€λ¨λμμ λ Continuation κ°μ²΄λ₯Ό λ°νν©λλ€.
μ€λ λμμ μ°¨μ΄μ μ?
- μ€λ λλ μ μ₯μ΄ λΆκ°λ₯νκ³ , λ©μΆλ κ²λ§ κ°λ₯ν©λλ€.
- μ½λ£¨ν΄μ΄ Continuation κ°μ²΄λ₯Ό λ°ννμ¬ λ©μ·λ κ³³μμ λ€μ μ½λ£¨ν΄μ μμνμ§λ§ μ€λ λλ μ μ₯μ΄ λΆκ°λ₯ν©λλ€.
- μ½λ£¨ν΄μ λν μ€λ¨νμ λ μ΄λ€ μμλ μ¬μ©νμ§ μμΌλ©°, λ€λ₯Έ μ€λ λμμ μμν μ μμ΅λλ€.
- 컨ν°λ΄μμ΄μ κ°μ²΄λ μ§λ ¬νμ μμ§λ ¬νκ° κ°λ₯νλ©° λ€μ μ€νλ μ μμ΅λλ€.
μ¬κ°
- μμ μ μ¬κ°νλ €λ©΄ μ½λ£¨ν΄μ΄ νμνλ©°, runblockingμ΄λ launchμ κ°μ μ½λ£¨ν΄ λΉλλ₯Ό νμ©ν μ μμ΅λλ€.
- μ€λ¨ ν¨μλ suspend ν€μλλ₯Ό νμ©νλ©°, λ°λμ μ½λ£¨ν΄μ μν΄ νΈμΆλμ΄μΌ ν¨μ μλ―Έν©λλ€.
suspend fun main() {
println("Before")
println("After")
}
// Before
// After
- λ§μ½ λ μ§μ μ¬μ΄λ₯Ό μ€λ¨νκ³ μΆλ€λ©΄ suspendCoroutine ν¨μλ₯Ό μ¬μ©ν μ μμ΅λλ€.
suspend fun main() {
println("Before")
suspendCoroutine<Unit> { continuation ->
println("Before too")
}
println("After")
}
// Before
// Before too
- main ν¨μλ λλμ§ μκΈ° λλ¬Έμ, Afterλ μΆλ ₯λμ§ μμ΅λλ€.
- suspendCoroutine ν¨μλ μ΄ ν¨μλ€κ³Ό κ°μ λ°©μμΌλ‘ μ€κ³λμ΄ μμ΄ μ€λ¨λκΈ° μ μ 컨ν°λ΄μμ΄μ κ°μ²΄λ₯Ό μ¬μ©ν μ μμ΅λλ€.
continuation.resume(Unit) // Kotlin 1.3 μ΄μ
continuation.resumeWith(Unit) // Kotlin 1.3 μ΄ν
- μ μ½λλ₯Ό suspendCoroutine λ΄λΆμμ μ€ννλ€λ©΄, μ€λ¨λ μ½λ£¨ν΄μ λ°λ‘ μ€νν μ μμ΅λλ€.
- νμ¬ resumeκ³Ό resumeWithException ν¨μλ resumeWithμ μ¬μ©νλ νμ€ λΌμ΄λΈλ¬λ¦¬μ νμ₯ ν¨μκ° λμμ΅λλ€.
μ μ§λ λ€ λ€λ₯Έ μ€λ λ μ€ν
suspend fun main() {
println("Before")
suspendCoroutine<Unit> { continuation ->
thread {
println("Suspended")
Thread.sleep(1000)
continuation.resume(Unit)
println("Resumed")
}
}
println("After")
}
// Before
// Suspended
// ... 1μ΄ ν
// After
// Resumed
- μ€μ λ‘λ μ€λ¨ λ ν 곧λ°λ‘ μ€νλλ κ²μ΄ μλ, μ΅μ νλ‘ μΈν΄ μ¬κ°λ κ²½μ° μμ μ€λ¨λμ§ μμ΅λλ€.
- νμ§λ§ λ§λ€μ΄μ§ λ€μ 1μ΄ λ€μ μ¬λΌμ§λ μ€λ λλ λΆνμν΄ λ³΄μ΄λ©°, μ€λ λλ₯Ό μμ±νλ λΉμ©μ μκ°νμ λ λ μ’μ λ°©λ²μ λͺ¨μν΄μΌ ν©λλ€.
coroutine delay ꡬν
private val excutor =
Executors.newSingleThreadScheduleExecutor {
Thread(it, "scheduler").apply { isDaemon = true }
}
suspend fun delay(timeMillis: Long): Unit =
suspendCoroutine { cont ->
executor.schedule({
cont.resume(Unit)
}, timeMillis, TimeUnit.MILLISECONDS)
}
suspend fun main() {
println("Before")
delay(1000)
println("After")
}
// Before
// 1μ΄ ν ...
// After
- excutorμμ μ€λ λλ₯Ό νμ©νμ§λ§, delay ν¨μλ₯Ό μ¬μ©νλ λͺ¨λ μ½λ£¨ν΄μ μ μ© μ€λ λμ΄λ©°, λκΈ°ν λλ§λ€ νλμ μ€λ λλ₯Ό λΈλ‘νΉνλ λ°©λ²λ³΄λ€ ν¨μ¬ μ’μ΅λλ€.
- μ€μ μ½λ£¨ν΄ λΌμ΄λΈλ¬λ¦¬μμμ delayμ ꡬν λ°©μμ΄ μ νν μΌμΉνλ©°, ν μ€νΈλ₯Ό μν΄ delayλ₯Ό ꡬ체ν νμμ΅λλ€.
κ°μΌλ‘ μ¬κ°νκΈ°
- resume ν¨μλ Unitμ μΈμλ‘ λ£λλ°, κ·Έ μ΄μ λ ν¨μμ λ¦¬ν΄ νμ μ λͺ μνλ κ²μ λλ€.
- Unitμ Continuationμ μ λ€λ¦ νμ μΈμλ‘λ νμ©λ©λλ€.
val ret: Unit =
suspendCoroutine<Unit> { cont: Continuation<Unit> ->
cont.resume(Unit)
}
val i: Int = suspendCoroutine<Int> { cont ->
cont.resume(42)
}
- μμ κ°μ΄ νμ μ μ§μ νλ κ²λ κ°λ₯νλ©°, νμ μ μ§μ νλ κ²½μ°λ resumeμ ν΅ν΄ λ°νλλ νμ μ΄ μ§μ νμ κ³Ό λ°λμ κ°μμΌ ν©λλ€.
- κ°μΌλ‘ μ¬κ°νλ μν©μ μ§μ ν κ³³μμ μ¬κ°ν λ κΈ°μ‘΄κ³Ό λ€λ₯Έ 무μμΈκ°λ₯Ό μΆκ°νλ κ²μ μ΄λ ΅μ΅λλ€.
- νμ§λ§ μ½λ£¨ν΄μμλ κ°μΌλ‘ μ¬κ°νλ κ²μ μμ°μ€λ½κ² μ²λ¦¬ν μ μμ΅λλ€.
μ½λ£¨ν΄μ κ°μΌλ‘ μ¬κ°νκΈ°
- APIλ₯Ό νΈμΆν΄ λ€νΈμν¬ μλ΅μ κΈ°λ€λ¦¬λ λ±μ νΉμ λ°μ΄ν°λ₯Ό μν μ€λ¨μ μμ£Ό λ°μν©λλ€.
- μ΄λ¬ν μν©μμ μ½λ£¨ν΄μ΄ μλ€λ©΄ μ€λ λλ μλ΅μ κΈ°λ€λ¦¬λ μν©λ§ κ°λ₯ν΄μ§λλ€.
- μ€λ λλ₯Ό μμ±νλ λΉμ©μ΄ λ§μ΄ λ€λ©°, μλλ‘μ΄λμ²λΌ λ©μΈ μ€λ λκ° μ€μνκ² μ μ©νλ κ²½μ° λ§€μ° ν° λλΉλ‘ μ΄μ΄μ§ μ μμ΅λλ€.
- “λ°μ΄ν°λ₯Ό λ°κ³ λλ©΄, λ°μ λ°μ΄ν°λ₯Ό resumeμΌλ‘ μ μ‘ν΄λΌ”μ κ°μ Continuation κ°μ²΄λ₯Ό ν΅ν΄ λΌμ΄λΈλ¬λ¦¬μ μ λ¬νλ€λ©΄, μ€λ λλ μ€κ°μ λ€λ₯Έ μΌμ ν μ μμ΅λλ€.
- κ·Έ ν λ°μ΄ν°κ° λμ°©νλ©΄ μ€λ λλ μ½λ£¨ν΄μ΄ μ€λ¨λ μ§μ μμ μ¬κ°ν μ μμ΅λλ€.
suspend fun main() {
println("Before")
val user = suspendCoroutine<User> { cont ->
requestUser { user ->
cont.resume(user)
}
}
println(user)
println("After")
}
// Before
// λ°μ΄ν°λ₯Ό λ°λ μκ° κ²½κ³Ό
// User(name = Test)
// After
- μ κ²½μ° νΉμ λ°μ΄ν°λ₯Ό μ»μ λκΉμ§ μ€λ¨λλ μν©μ μ»μ μ μμΌλ©°, μ€λ λκ° μλ΅μ κΈ°λ€λ¦¬μ§ μκ³ , λ€λ₯ΈμΌμ μ²λ¦¬ν μ μμ΅λλ€.
- user κ°μ²΄κ° λμ°©νλ€λ©΄, μ€λ λλ μ½λ£¨ν΄μ΄ μ€λ¨λ μμ μμ μ¬κ°λμ΄ μ¬μ©μκ° μνλ κ°μ κΈ°λν μ μμ΅λλ€.
μμΈλ‘ μ¬κ°νκΈ°
- λ§μ½ APIκ° λ°μ΄ν°λ₯Ό λ겨주λ κ³Όμ μμ μλ¬κ° λ°μνλ€λ©΄, λ°μ΄ν°λ₯Ό λ°νν μ μμΌλ―λ‘ μ½λ£¨ν΄μ΄ μ€λ¨λ κ³³μμ μμΈλ₯Ό λ°μμμΌμΌ ν©λλ€.
class MyException : Throwable("custom exception")
suspend fun main() {
try {
suspendCoroutine<Unit> { cont ->
cont.resumeWithException(MyException())
}
} catch (e: MyException) {
println("${e.message}")
}
}
ν¨μκ° μλ μ½λ£¨ν΄μ μ€λ¨
- μ€λ¨ ν¨μλ μ½λ£¨ν΄μ΄ μλ, λ¨μ§ μ½λ£¨ν΄μ μ€λ¨ν μ μλ ν¨μλΌ ν μ μμ΅λλ€.
var continuation: Continuation<Unit>? = null
suspend fun suspendAndSetContinuation() {
suspendCoroutine<Unit> { cont ->
continuation = cont
}
}
suspend fun main(){
println("Before")
suspendAndSetContinuation()
continuation?.resume(Unit)
println("After")
}
// Before
- μ μ½λλ μλͺ» λ ꡬνμ μμλ‘ λ€κ³ μμ΅λλ€.
- μλμ λ¬λ¦¬ μ’ λ£λμ§ μμΌλ©°, resumeμ΄ νΈμΆλμ§ μμμ΅λλ€.
- κ·Έ μ΄μ λ suspendAndSetContinuation()λ₯Ό ν΅ν΄ μ€λ¨ μ§μ μ μμ±νκ³ μ½λ£¨ν΄μ μΌμ μ€λ¨ νμμ§λ§, continuationμ΄ λ€μ νΈμΆλκΈ° μ κΉμ§ μ½λ£¨ν΄μ΄ μ¬κ°λμ§ μμ΅λλ€.
- continuation?.resume(Unit)λ₯Ό ν΅ν΄μ μ½λ£¨ν΄μ μ¬κ°νμ§λ§, μ΄ μ½λλ μμ§ main ν¨μμ μΌμ μ€λ¨λ μ§μ μμ μ¬κ°λμ§ μμμ΅λλ€.
- main ν¨μκ° λΉλκΈ°μ μΌλ‘ λμνκ³ , continuation?.resume(Unit)μ΄ νΈμΆλκΈ° μ μ νλ‘κ·Έλ¨μ΄ μ’ λ£λμκΈ° λλ¬Έμ΄λ©°, resume()μ νΈμΆμ main ν¨μκ° μ’ λ£λκΈ° μ μ μλ£λμ§ μμμ΅λλ€.
- μ΄λ λ©λͺ¨λ¦¬ λμκ° λ°μν μ μμ΅λλ€.
var continuation: Continuation<Unit>? = null
suspend fun suspendAndSetContinuation() {
suspendCoroutine<Unit> { cont ->
continuation = cont
}
}
fun main() = runBlocking {
println("Before")
suspendAndSetContinuation()
continuation?.resume(Unit)
println("After")
}
- μμ κ°μ΄ runBlockingμ νμ©νμ¬ main ν¨μκ° μ½λ£¨ν΄μ μλ£λ₯Ό κΈ°λ€λ¦¬κ² νλ€λ©΄ λ¬Έμ λ₯Ό ν΄κ²°ν μ μμ΅λλ€.
https://m.yes24.com/Goods/Detail/123034354