DispatchQueue
작업 항목의 실행을 관리하는 클래스
애플리케이션에서 작업을 비동기 및 동시에 수행할 수 있게 해주는 GCD 대기열 위에 있는 추상화 계층
일반 스레드 보다 쉽고 효율적으로 코드를 작성할 수 있다. 보통 서버에서 데이터를 받고 이미지 동영상을 외부에서 다운로드 및 처리할 때 CPU 사용량이 많아 처리를 메인 스레드가 아닌 별도의 스레드에서 처리한 뒤 메인 스레드로 결과만을 전달하여 화면에 표시하도록 하여 CPU를 관리할 수 있다.
DispatchQueue 의 종류 - Serial / Concurrent
Serial Dispatch Queue - 비동기
이전 작업이 끝나면 다음 작업을 순차적으로 실행하는 직렬 형태의 큐.
하나의 작업을 실행하고 그 실행이 끝날 때까지 대기열에 있는 다른 작업을 잠시 미루고 있다가 직전의 작업이 끝나면 실행한다.
한 번에 하나의 작업만 수행합니다.
직렬 대기열은 특정 값이나 리소스에 대한 액세스를 동기화하여 데이터 경합이 발생하지 않도록 하는 데 자주 사용됩니다.
let serialQueue = DispatchQueue(label: "swiftlee.serial.queue")
serialQueue.async {
print("Task 1 started")
// Do some work..
print("Task 1 finished")
}
serialQueue.async {
print("Task 2 started")
// Do some work..
print("Task 2 finished")
}
/*
Serial Queue prints:
Task 1 started
Task 1 finished
Task 2 started
Task 2 finished
*/
Concurrent Dispatch Queue - 동기
이전 작업이 끝날 때 까지 기다리지 않고 병렬 형태로 동시에 실행되는 큐.
즉 대기열에 있는 작업을 동시에 별도의 스레드를 사용하여 실행한다.
let concurrentQueue = DispatchQueue(label: "swiftlee.concurrent.queue", attributes: .concurrent)
concurrentQueue.async {
print("Task 1 started")
// Do some work..
print("Task 1 finished")
}
concurrentQueue.async {
print("Task 2 started")
// Do some work..
print("Task 2 finished")
}
/*
Concurrent Queue prints:
Task 1 started
Task 2 started
Task 1 finished
Task 2 finished
*/
경우에 따라서 데이터 경합을 방지하면서 동시에 여러 작업을 수행할 필요가 있다.
barrier flag 를 추가 하면 가능하다!
변수를 쓰기 전까지 읽기를 차단하는 방법이다.
final class Messenger {
private var messages: [String] = []
private var queue = DispatchQueue(label: "messages.queue", attributes: .concurrent)
var lastMessage: String? {
return queue.sync {
messages.last
}
}
func postMessage(_ newMessage: String) {
queue.sync(flags: .barrier) {
messages.append(newMessage)
}
}
}
let messenger = Messenger()
// Executed on Thread #1
messenger.postMessage("Hello SwiftLee!")
// Executed on Thread #2
print(messenger.lastMessage) // Prints: Hello SwiftLee!
Main Dispatch Queue
메인 디스패치 큐는 애플리케이션의 메인 스레드에서 작업을 실행하는 전역적으로 사용 가능한 직렬 큐이다.
기본 스레드는 UI 업데이트에 사용되므로 이 대기열에서 작업을 실행할 때 의식하는 것이 중요합니다.
따라서 앞에서 설명한 디스패치 API를 사용하여 다른 스레드에서 작업을 수행하는 것이 좋습니다.
백그라운드 대기열에서 무거운 작업을 시작하고 완료되면 기본 대기열로 다시 파견할 수 있습니다.
let concurrentQueue = DispatchQueue(label: "swiftlee.concurrent.queue", attributes: .concurrent)
concurrentQueue.async {
// Perform the data request and JSON decoding on the background queue.
fetchData()
DispatchQueue.main.async {
/// Access and reload the UI back on the main queue.
tableView.reloadData()
}
}
유아이 작업은 메인 스레드 에서 해줘야 됨!
과도한 스레드 생성 방지
너무 많은 차단 작업이 concurrent dispatch queues에 추가되어 시스템에서 앱의 스레드가 부족해질 때까지 추가 스레드를 생성하는 경우 에는 문제가 될 수 있다.
global concurrent dispatch queues 를 사용해주면 너무 많은 추가 스레드를 방지할 수 있다.
QoS 를 통해 우선순위를 결정해 줄 수 있다. 우선순위가 높은 작업은 낮은 순위의 작업보다 더 빨리 실행되며, 이를 잘 적용하면 빠른 앱을 만들 수 있다.
DispatchQueue.global().async {
/// Concurrently execute a task using the global concurrent queue. Also known as the background queue.
}
This global concurrent queue is also known as the background queue and used next to the DispatchQueue.main.
https://www.avanderlee.com/swift/concurrent-serial-dispatchqueue/
https://seons-dev.tistory.com/entry/Swift-DispatchQueue%EB%9E%80-GCD-Grand-Central-Dispatch
'# 02 > Swift' 카테고리의 다른 글
[Swift] 기초 입문 Study (0) | 2023.07.21 |
---|---|
[Swift] RxSwift (0) | 2023.01.11 |
[Swift] DFS/BFS (0) | 2022.12.18 |
[Swift] MaxHeap (0) | 2022.12.12 |
[Swift] MinHeap (0) | 2022.12.12 |