GCD
- Grand Central Dispatch
- 모든 애플 플랫폼에서 사용 가능
- 스레드 생성, 관리
- 스레드 풀을 통해 스레드 재사용, 시스템 리소스를 적게 사용
Dispatch Queue & Work Item
- GCD의 핵심 개체
Work Item
: 실행할 코드
Dispatch Queue
: 작업을 관리하는 객체
- Dispatch Queue에 Work Item을 추가하면 추가한 순서대로 작업이 실행된다. 이러한 모델을
Work-Queue Programming Model
이라고 한다.
Serial Queue & Concurrent Queue
- Dispatch Queue의 작업 방식
Serial Queue
: 추가된 작업을 순서대로 실행(기본)
Concurrent Queue
: 동시에 작업을 실행(concurrent 옵션으로 생성)
Global Queue & Main Queue
DispatchQueue.global().async{
for num in 1 ... 100{
DispatchQueue.main.async{
self.countLabel.text = "\(num)"
}
Thread.sleep(forTimeInterval: 0.1)
}
}
global
: 백그라운드 스레드에서 동작하는 기본 큐
main
: 메인스레드에서 동작하는 기본 큐
- 메인 큐는 앱 시작 시점에 자동으로 생성
- serial 함
- UI에 관련된 작업은 반드시 main에서 실행
Dispatch Queue 생성
let serialQueue = DispatchQueue(label: "SerialQueue")
let concurrentQueue = DispatchQueue(label: "ConcurrentQueue", attributes: .concurrent)
Work Item 생성
sync & async
@IBAction func sync(_ sender: Any) {
concurrentQueue.sync {
for _ in 0 ..< 3 {
print("Hello")
}
print("# Point 1")
}
print("# Point 2")
}
@IBAction func async(_ sender: Any) {
concurrentQueue.async {
for _ in 0 ..< 3 {
print("Hello")
}
print("# Point 1")
}
print("# Point 2")
}
- sync, async는 실행하는 메소드가 아닌, 큐에 work item을 추가하는 메소드다.
- 실제 작업 실행은 dispatchQueue
- async와 sync가 dispatchQueue의 동작 방식에는 영향을 주지 않는다.
- serial Queue에 추가할 때 둘 중 어느것을 사용하던 항상 작업을 순서대로 실행한다.
- concurrent Queue에 추가할 때 둘 중 어느것을 사용하던 동시에 작업을 실행한다.
sync 결과
- sync는 동기 방식으로 work를 추가
- work아이템을 추가한 다음 바로 리턴하지 않고 실행이 끝날 때까지 기다린다.
- 주로 lock과 유사한 동기화를 구현할 때 사용
- mainQueue에서 sync를 사용하면 크래시가 발생하므로 주의하자.
async 결과
- async는 비동기 방식으로 work를 추가
- work아이템을 추가한 다음 바로 리턴하므로 이어지는 코드가 바로 실행된다.
- 스레드를 블로킹하지 않으므로 대부분은 async로 work 아이템을 추가한다.
asyncAfter로 실행 시간 지연
@IBAction func delay(_ sender: Any) {
let delay = DispatchTime.now() + 10
concurrentQueue.asyncAfter(deadline: delay) {
print("# Point 1")
}
print("# Point 2")
}
Point 2 바로 출력 후 10초 뒤에 Point 1 출력
asyncAfter
은 비동기 메소드
- 지정한 시간에 작업을 예약하고 바로 리턴
병렬 실행
DispatchQueue.concurrentPerform(iterations: , execute: (Int) -> Void)
- execute 블럭을 iterations만큼의 횟수로 병렬 실행
@IBAction func concurrent(_ sender: Any) {
var start = Date.now
for index in 0 ..< 50 {
print(index, terminator: " ")
Thread.sleep(forTimeInterval: 0.1)
}
print()
var end = Date.now
print("serial: \(end.timeIntervalSinceReferenceDate - start.timeIntervalSinceReferenceDate)")
start = Date.now
DispatchQueue.concurrentPerform(iterations: 50) { index in
print(index, terminator: " ")
Thread.sleep(forTimeInterval: 0.1)
}
print()
end = Date.now
print("serial: \(end.timeIntervalSinceReferenceDate - start.timeIntervalSinceReferenceDate)")
}
- 보통 병렬로 실행할 수 있는 작업의 수는 CPU의 코어 수와 동일