λ³Έ κ²μλ¬Όμ μ¨λ°μ μΈνλ° κ°μλ₯Ό λ£κ³ μμ±ν κΈ μ λλ€.
1. Dispatch Groupμ κ°λ
μμ νλμ μμ μ΄ λλλ©΄ κ·Έ μμ μ΄ λλλ μμ μ λν΄ μ μ μμλ€. κ·Έλ¬λ κ·Έλ° μμ λ€μ λ 립μ μ΄μκΈ° λλ¬Έμ μ¬λ¬κ°μ§ μμ μ κ·Έλ£Ήμ§μ΄ νλμ κ·Έλ£ΉμΌλ‘ λ¬Άμ΄ μ΄λ° κ·Έλ£ΉμΌλ‘ λ¬ΆμΈ μμ μ΄ λλλ μμ μ μκ³ μΆμ λ λμ€ν¨μΉ κ·Έλ£Ήμ μ¬μ©νλ€.
μ¬λ¬ μμ μ κ·Έλ£ΉμΌλ‘ λ¬ΆμΈ μμ μ΄λΌ νλ©΄ μ΄λ―Έμ§λ₯Ό μ¬λ¬κ° λ€μ΄λ‘λ λ°κ³ μΆμ λ νλμ μ΄λ―Έμ§λ₯Ό λ€μ΄λ‘λ λ°λκ²μ νλμ μμ μ΄λΌκ³ 보면 μ΄λ° μμ μ μ¬λ¬κ° λ¬Άμ΄ μ¬λ¬κ°μ μ΄λ―Έμ§λ₯Ό λ€μ΄λ‘λ λ°λ κ²μ νλμ κ·Έλ£Ήμ λ¬Άμ΄ μ¬μ©ν μ μλ€.
3κ°μ κ·Έλ£Ήμ λ¬ΆμΈ μμ μ 3κ°μ μ€λ λμμ μ¬μ©ν κ²½μ° μ¬λ¬ μ€λ λμμ μμ μ μ²λ¦¬νμ§λ§ κ° κ·Έλ£Ήμ μμ μ΄ λλ μμ μ μ μ μλ€.
let group1 = DispatchGroup()
DispatchQueue.global(qos: ).async(group: group1) { }
DispatchQueue.global(qos: ).async(group: group1) { }
DispatchQueue.global().async(group: group1) { }
group1.notify(queue: DispatchQueue.main) { [weak self] in
self?.textLabel.text = "λͺ¨λ μμ
μ΄ μλ£λμμ΅λλ€."
}
μ μ½λμμ group1μ΄λΌλ μ΄λ¦μΌλ‘ DispatchGroupμ μμ±νλ€.
λ€μ νλ‘ λ³΄λΌ λ, μ΄λ€ κ·Έλ£Ή(group1)μ λ£μ κ²μΈμ§ μ ν΄μ€λ€. μ΄λ κ² μ μ΄ κ·Έλ£Ήμ λ£μ΄μ£Όλ©΄ μμμ μμ μ΄ μ μ΄μ€ κ·Έλ£Ή(group1)μ λ¬ΆμΈλ€.
λ°λΌμ λλ²μ§Έ λ¨λ½μ μλ 3μ€μ μ½λκ° κ°μ κ·Έλ£ΉμΌλ‘ λ¬Άμ΄κ³ , κ°κ° νμ€μ νλμ μμ μμ μ μ μλ€.
λ§μ§λ§μ notify()λ₯Ό ν΅ν΄ μμ μ΄ μλ£λ¨μ μλ¦°λ€. notify()λ λͺ¨λ κ·Έλ£Ήμ μμ μ΄ λλλ μμ μ μ€νλλ μ½λμ΄λ€.
μ΄λ, 맀κ°λ³μλ‘ queueλ₯Ό mainμΌλ‘ μ€μ ν΄ μ€μΌλ‘μ¨ μ΄ notifiyλ mainμμ μ€νλλ€.
wait()
μ΄λ€ μ΄μ λ‘ κ·Έλ£Ήμ μλ£ μλ¦Όμ λΉλκΈ°μ μΌλ‘ μλ΅ ν μ μλ κ²½μ°, λμ λμ€ν¨μΉ κ·Έλ£Ήμμ wait()μ μ¬μ©ν μ μλ€.
μ΄λ λͺ¨λ μμ μ΄ μλ£ λ λκΉμ§ νμ¬ λκΈ°μ΄μ μ°¨λ¨νλ λκΈ°μ λ°©λ²μ΄λ€. μμ μ΄ μλ£λ λκΉμ§ μΌλ§λ μ€λ κΈ°λ€λ¦΄μ§ κΈ°λ€λ¦¬λ μκ°μ μ§μ νλ νλΌλ―Έν°κ° νμνλ€. μ΄λ μ νμ μΌλ‘ μ§μ νλ©° μ μ΄μ£Όμ§ μμΌλ©΄ 무μ νμΌλ‘ λκΈ°νλ€.
μλ₯Όλ€μ΄, λ€νΈμν¬ ν΅μ μ νλ κ²½μ° μ΄λ ν μ΄μ λ‘ μκ°μ΄ μ€λ κ±Έλ¦΄κ²½μ° μΈμ κΉμ§ μλ΅μ κΈ°λ€λ¦΄ μλ μλ€. 무νμ μΌλ‘ κΈ°λ€λ¦¬λ κ²μ μ¬μ©μμκ² λΆνΈμ μ€ μ μκΈ° λλ¬Έμ wait()μ μ μ ν νμ©νμ¬ νλ©΄μ μ μ΄νλ€.
let group1 = DispatchGroup()
DispatchQueue.global(qos: ).async(group: group1) { }
DispatchQueue.global(qos: ).async(group: group1) { }
DispatchQueue.global().async(group: group1) { }
group1.wait(timeout: DispatchTime.distantFuture)
μ μ½λμμ waitλ©μλλ₯Ό μ΄μ©ν΄ κΈ°λ€λ¦¬λ μκ°μ μ€μ νλ€. distantFutureλ‘ μ€μ λμ΄ μκΈ° λλ¬Έμ 무νμ μΌλ‘ κΈ°λ€λ¦°λ€.
group1.wait(timeout: .now() + 60) == .timedOut {
print("μμ
μ΄ 60μ΄μμ μ’
λ£νμ§ μμμ΅λλ€.")
}
μ΄μ²λΌ μ μ΄μ£Όλ©΄ 무νμ κΈ°λ€λ¦¬λκ² μλ μ§κΈ μκ°μΌλ‘λΆν° 60μ΄κ° κΈ°λ€λ¦°λ€. 60μ΄λμ μμ μ΄ μλ£λμ§ μμ printλ¬Έμ΄ μ€νλμ΄λ μμ μ΄ λ©μΆλ κ²μ΄ μλλΌ κ³μ μ§νλκΈ°λ νλ€.
μ€μ μ±μμ λ©μΈν(λ©μΈμ€λ λ)μμλ wait()μ μ¬μ©νλ©΄ μλλ€. λ©μΈνμμ μ€ννκ² λλ©΄ κΈ°λ€λ¦¬λ λμ mainμ blockμνκ° λλλ° μ΄λ¬λ©΄ UIκ° λ©μΆκΈ° λλ¬Έμ΄λ€.
2. Dispatch Groupμ μ¬μ©
μ μ½λλ λκΈ°μ ν¨μλ₯Ό μ€νν λμ μ½λμλ€. λ§μ½ ν΄λ‘μ λ΄μμ λΉλκΈ°ν¨μλ₯Ό νΈμΆν λ μ΄λ€ λ¬Έμ κ° μμκΉ?
λ§μ½ λΉλκΈ° ν¨μλ₯Ό μ€ννλ©΄ λ€λ₯Έ μ€λ λμμ μΌνλλ‘ μμ μ 보λ΄κ³ λ°λ‘ 리ν΄νλ€. μ΄λ¬ν κ³Όμ μμ κ·Έλ£ΉμΌλ‘ λ¬Άμ¬μλ μμ μ΄ λλλ μμ μ μλͺ» μΈμν μ μλ€.
μ΄λ¬ν λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ enter()μ leave()λ₯Ό νμ©νλ€.
μμ μ μμν λ enter()λ₯Ό μ€ννκ³ , λλ λ leave()λ₯Ό μ€νν¨μΌλ‘μ¨ λ ν¨μμ κ°μκ° κ°μμ§ λ μ§μ§λ‘ λλ μμ μΌλ‘ μΈμνλ κ²μ΄λ€.
queue.async(group: group1) {
group1.enter() // μ
μ₯
someAsyncMethod {
group1.leave() // ν΄μ₯
}
}
μ μ½λμ²λΌ enterλ©μλ(μ μ₯)μ leaveλ©μνΈ(ν΄μ₯)μ κ°μκ° κ°μμ§λ©΄ μ’ λ£λλ€.
3. Dispatch workItem
Dispatch workItemμ΄λ νλμ μμ μ체λ₯Ό ν΄λμ€ν νμ¬ μμ μ 미리 μ μν΄λκ³ μ¬μ©νλ νμ μ μΆνκΈ° μν κ°μ²΄μ΄λ€.
λΉμ½ν μ·¨μκΈ°λ₯κ³Ό λΉμ½ν μμκΈ°λ₯μ λ΄μ₯νκ³ μλ€.
let item1 = DispatchWorkItem(qos: .utility) {
print("task1: μΆλ ₯νκΈ°")
print("task2: μΆλ ₯νκΈ°")
}
let item2 = DispatchWorkItem {
print("task3: μΆλ ₯νκΈ°")
print("task4: μΆλ ₯νκΈ°")
}
let queue = DispatchQueue(label: "com.inflearn.serial")
queue.async(execute: item1)
queue.async(execute: item2)
μ μ½λμ κ°μ΄ μ¬μ©νλ©°, qosλ₯Ό μ μ΄μ£Όμ§ μμΌλ©΄ λν΄νΈλ‘ μ€μ λλ€.
λΉμ½ν μ·¨μκΈ°λ₯
cancel()κ° μ‘΄μ¬νλ€.
μ΄λ μμ μ΄ μμ§ μμλμ§ μμ κ²½μ° μμ μ΄ μ κ±°λκ³ , μμ μ΄ μ€νμ€μΈ κ²½μ° inCancelledμμ±μ΄ trueλ‘ μ€μ λλ€.
λ¨, μ§μ μ μΌλ‘ μ€νμ€μΈ μμ μ΄ λ©μΆλ κ²μ μλλ€. λ¨μν μμ± μ€μ λ§ νλκ²μ΄λ©°, μ΄λ₯Ό μ΄μ©ν΄ μΆκ°μ μΈ μμ μ€νμ¬λΆλ₯Ό μ€μ ν μ μλ€.
let item1 = DispatchWorkItem(qos: .utility) {
print("task1: μΆλ ₯νκΈ°")
print("task2: μΆλ ₯νκΈ°")
}
item1.cancel()
let queue = DispatchQueue(label: "com.inflearn.serial")
queue.async(execute: item1)
queue.async(execute: item2)
μ μ½λμμ item1.cancel()μ ν¨μΌλ‘μ¨, item1μ΄ μ·¨μλμ΄ μλ queue.async(execute: item1)μ΄ μ€νλμ§ μλλ€.
λΉμ½ν μμκΈ°λ₯
notify()κ° μ‘΄μ¬νλ€.
notify(queue: λ€μ μμ μ μ€νν ν, execute: λμ€ν¨μΉ μμ΄ν (μ΄λ€ μμ λ€)) λ©μλκ° μ‘΄μ¬νλ€.
μ§μ μ μΌλ‘ μ€νν ν λ€μ μ€νν μμ μ μ§μ νλ€.
item1.notify(queue: DispatchQueue.global(), execute: item2)
queue.async(execute: item1)
μ μ½λμμ item1μ΄ μ€νλ ν item2κ° μ€νλλ€.
4. Semaphore(μΈλ§ν¬μ΄)μ μ΄ν΄
μ΄λ 곡μ 리μμ€μ μ κ·Όκ°λ₯ν μμ μλ₯Ό μ νν΄μΌν κ²½μ° μ¬μ©νλ€. μλ₯Ό λ€μ΄ λ€μ΄λ‘λ μ«μλ₯Ό μ νν΄μΌ ν λ 10κ°μ μ€λ λκ° μλ 2κ°λ§ μ¬μ©νλλ‘ μ νν λ μ¬μ©νλ€.
let semaphore = DispatchSemaphore(value: 3)
queue.async(group: group1) {
group1.enter()
semaphore.wait()
someAsyncMethod {
group.leave()
semaphore.signal()
}
}
wait()μΌλ‘ μΌλ¨ κΈ°λ€λ¦¬κ² νμ¬ μμ μλ₯Ό μ ννλ€. νμ μλμμ signal()μΌλ‘ μμ μ΄ λλ¬μΌλ―λ‘ λ€μ μμ μ μμνλλ‘ μ€μ νλ€.
μ 체 μ΄μ©κ°λ₯ν κ°μ΄ 3μΌ λ, wait()μ μ€ννλ©΄ μ€μ λ΄λΆ μμ μ κ°μ΄ 1μ€μ΄ μ΄μ© κ°λ₯ν μμμλ 2κ° λλ€. νμ signal()μ μ€ννλ©΄ 1μ¦κ°μμΌ μ΄μ© κ°λ₯ν μμμλ 3μ΄ λκ³ wait()κ³Ό signal()μ ν΅ν΄ μ«μκ° 3(μ΄μ©κ°λ₯ν μμμ)λ₯Ό μ΄κ³Όνμ§ μλλ‘ κ΄λ¦¬νλ€.
*λΉκ΅
enter(), leave() -> λ€μ΄κ°κ³ λκ°κ³ μ μ«μλ₯Ό λ§μΆ°μ λͺ¨λ μμ μ΄ λλ¬μμ μκΈ° μν κ°λ
wait(), signal() (μΈλ§ν¬μ΄) -> νλ²μ μ€νκ°λ₯ν μμ μ κ°μ μ ν