Swift 5.1에서 Grand Central Dispatch 는 문제를 해결하는 여러 가지 방법을 제공합니다. 필요 에 따라 다음 놀이터 스 니펫에 표시된 7 가지 패턴 중 하나를 선택할 수 있습니다 .
Apple Developer Concurrency Programming Guide는 다음에 대해 설명합니다DispatchGroup
.
디스패치 그룹은 하나 이상의 작업이 완료 될 때까지 스레드를 차단하는 방법입니다. 지정된 모든 작업이 완료 될 때까지 진행할 수없는 장소에서이 동작을 사용할 수 있습니다. 예를 들어, 일부 데이터를 계산하기 위해 여러 태스크를 디스패치 한 후 그룹을 사용하여 해당 태스크를 기다린 후 완료되면 결과를 처리 할 수 있습니다.
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue(label: "com.company.app.queue", attributes: .concurrent)
let group = DispatchGroup()
queue.async(group: group) {
print("#1 started")
Thread.sleep(forTimeInterval: 5)
print("#1 finished")
}
queue.async(group: group) {
print("#2 started")
Thread.sleep(forTimeInterval: 2)
print("#2 finished")
}
group.notify(queue: queue) {
print("#3 finished")
}
/*
prints:
#1 started
#2 started
#2 finished
#1 finished
#3 finished
*/
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue(label: "com.company.app.queue", attributes: .concurrent)
let group = DispatchGroup()
group.enter()
queue.async {
print("#1 started")
Thread.sleep(forTimeInterval: 5)
print("#1 finished")
group.leave()
}
group.enter()
queue.async {
print("#2 started")
Thread.sleep(forTimeInterval: 2)
print("#2 finished")
group.leave()
}
queue.async {
group.wait()
print("#3 finished")
}
/*
prints:
#1 started
#2 started
#2 finished
#1 finished
#3 finished
*/
당신은 또한 혼합 할 수 있습니다 DispatchGroup
wait()
으로 DispatchQueue
async(group:qos:flags:execute:)
또는 혼합 DispatchGroup
enter()
하고 DispatchGroup
leave()
와 DispatchGroup
notify(qos:flags:queue:execute:)
.
Swift 4 : Grand Central Dispatch Tutorial : Raywenderlich.com의 1/2 부 기사는 장벽에 대한 정의를 제공합니다 .
디스패치 배리어는 동시 큐 작업시 직렬 스타일 병목 현상으로 작동하는 기능 그룹입니다. DispatchWorkItem
디스패치 큐에 제출할 때 해당 특정 시간 동안 지정된 큐에서 실행되는 유일한 항목임을 나타내도록 플래그를 설정할 수 있습니다. 이는 발송 장벽 이전에 큐에 제출 된 모든 항목 DispatchWorkItem
이 실행 전에 완료되어야 함을 의미합니다 .
용법:
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue(label: "com.company.app.queue", attributes: .concurrent)
queue.async {
print("#1 started")
Thread.sleep(forTimeInterval: 5)
print("#1 finished")
}
queue.async {
print("#2 started")
Thread.sleep(forTimeInterval: 2)
print("#2 finished")
}
queue.async(flags: .barrier) {
print("#3 finished")
}
/*
prints:
#1 started
#2 started
#2 finished
#1 finished
#3 finished
*/
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue(label: "com.company.app.queue", attributes: .concurrent)
queue.async {
print("#1 started")
Thread.sleep(forTimeInterval: 5)
print("#1 finished")
}
queue.async {
print("#2 started")
Thread.sleep(forTimeInterval: 2)
print("#2 finished")
}
let dispatchWorkItem = DispatchWorkItem(qos: .default, flags: .barrier) {
print("#3 finished")
}
queue.async(execute: dispatchWorkItem)
/*
prints:
#1 started
#2 started
#2 finished
#1 finished
#3 finished
*/
Soroush Khanlou는 GCD 핸드북 블로그 게시물 에 다음과 같은 내용을 썼습니다 .
세마포를 사용하면 다른 스레드의 신호가 전송 될 때까지 임의의 시간 동안 스레드를 차단할 수 있습니다. 나머지 GCD와 마찬가지로 세마포어는 스레드로부터 안전하며 어디에서나 트리거 할 수 있습니다. 세마포어는 동기식으로 만들어야하는 비동기식 API가있는 경우 사용할 수 있지만 수정할 수는 없습니다.
Apple Developer API Reference는 DispatchSemaphore
init(value:)
이니셜 라이저에 대한 다음 설명도 제공합니다 .
값에 0을 전달하면 두 스레드가 특정 이벤트의 완료를 조정해야 할 때 유용합니다. 0보다 큰 값을 전달하면 한정된 리소스 풀을 관리하는 데 유용합니다. 여기서 풀 크기는 값과 같습니다.
용법:
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue(label: "com.company.app.queue", attributes: .concurrent)
let semaphore = DispatchSemaphore(value: 0)
queue.async {
print("#1 started")
Thread.sleep(forTimeInterval: 5)
print("#1 finished")
semaphore.signal()
}
queue.async {
print("#2 started")
Thread.sleep(forTimeInterval: 2)
print("#2 finished")
semaphore.signal()
}
queue.async {
semaphore.wait()
semaphore.wait()
print("#3 finished")
}
/*
prints:
#1 started
#2 started
#2 finished
#1 finished
#3 finished
*/
Apple Developer API Reference는 다음에 대해 설명합니다 OperationQueue
.
작업 대기열은 libdispatch
라이브러리 (Grand Central Dispatch라고도 함)를 사용하여 작업 실행을 시작합니다.
용법:
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let operationQueue = OperationQueue()
let blockOne = BlockOperation {
print("#1 started")
Thread.sleep(forTimeInterval: 5)
print("#1 finished")
}
let blockTwo = BlockOperation {
print("#2 started")
Thread.sleep(forTimeInterval: 2)
print("#2 finished")
}
let blockThree = BlockOperation {
print("#3 finished")
}
blockThree.addDependency(blockOne)
blockThree.addDependency(blockTwo)
operationQueue.addOperations([blockThree, blockTwo, blockOne], waitUntilFinished: false)
/*
prints:
#1 started
#2 started
#2 finished
#1 finished
#3 finished
or
#2 started
#1 started
#2 finished
#1 finished
#3 finished
*/
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let operationQueue = OperationQueue()
let blockOne = BlockOperation {
print("#1 started")
Thread.sleep(forTimeInterval: 5)
print("#1 finished")
}
let blockTwo = BlockOperation {
print("#2 started")
Thread.sleep(forTimeInterval: 2)
print("#2 finished")
}
operationQueue.addOperations([blockTwo, blockOne], waitUntilFinished: false)
operationQueue.addBarrierBlock {
print("#3 finished")
}
/*
prints:
#1 started
#2 started
#2 finished
#1 finished
#3 finished
or
#2 started
#1 started
#2 finished
#1 finished
#3 finished
*/