iOS
GCD (그랜드 센트럴 디스패치)
수색…
소개
Grand Central Dispatch (GCD)는 멀티 스레딩에 대한 애플의 대답입니다. 대기열에서 작업을 동 기적 또는 비동기 적으로 수행 할 수있는 가벼운 프레임 워크이며 뒤에서 CPU 스레드를 처리합니다.
관련 항목 : 동시성
디스패치 대기열 만들기
dispatch_queue_create
사용하여 고유 한 대기열을 만들 수 있습니다.
목표 -C
dispatch_queue_t queue = dispatch_queue_create("com.example.myqueue", DISPATCH_QUEUE_SERIAL);
빠른
// Before Swift 3
let queue = dispatch_queue_create("com.example.myqueue", DISPATCH_QUEUE_SERIAL)
// Swift 3
let queue = DispatchQueue(label: "com.example.myqueue") //default is serial queue, unless .concurrent is specified as an attribute otherwise
메인 큐 얻기
메인 큐는 모든 UI 업데이트가 발생하고 UI 변경과 관련된 코드가 배치되는 디스패치 큐입니다.
NSURLSession
과 같은 비동기 프로세스 완료시 UI를 업데이트하려면 메인 대기열에 도착해야합니다.
주 대기열 호출에는 synchronous
및 asynchronous
라는 두 가지 유형이 있습니다. synchronously
어떤 것을 호출하면 해당 작업을 시작한 스레드가 작업이 완료 될 때까지 기다릴 것임을 의미합니다. Asynchronous
는 기다리지 않는다는 것을 의미합니다.
코드 목적 - C
Synchronous
메인 대기열 통화
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
Asynchronous
메인 큐 호출
dispatch_async(dispatch_get_main_queue(), ^{
// do work here to Usually to update the User Interface
});
SWIFT 3
Asynchronous
메인 큐 호출
DispatchQueue.main.async {
}
Synchronous
메인 대기열 통화
DispatchQueue.main.sync {
}
파견 그룹
DispatchGroup은 작업의 집계 동기화를 허용합니다. 여러 대기열에서 실행될 수있는 경우에도이를 사용하여 여러 다른 작업 항목을 제출하고 모두 완료 할 때 추적 할 수 있습니다. 이 작업은 지정된 모든 작업이 완료 될 때까지 진행할 수 없을 때 도움이 될 수 있습니다.
계속 진행하기 전에 여러 웹 서비스 호출을 완료해야하는 경우에 유용 할 수 있습니다. 예를 들어, 일부 기능으로 처리해야하는 여러 데이터 세트를 다운로드해야합니다. 수신 된 모든 데이터를 처리하는 함수를 호출하기 전에 모든 웹 서비스가 완료 될 때까지 기다려야합니다.
스위프트 3
func doLongTasksAndWait () {
print("starting long running tasks")
let group = DispatchGroup() //create a group for a bunch of tasks we are about to do
for i in 0...3 { //launch a bunch of tasks (eg a bunch of webservice calls that all need to be finished before proceeding to the next ViewController)
group.enter() //let the group know that something is being added
DispatchQueue.global().async { //run tasks on a background thread
sleep(arc4random() % 4) //do some long task eg webservice or database lookup (here we are just sleeping for a random amount of time for demonstration purposes)
print("long task \(i) done!")
group.leave() //let group know that the task is finished
}
}
group.wait() //will block whatever thread we are on here until all the above tasks have finished (so maybe dont use this function on your main thread)
print("all tasks done!")
}
또는 그룹이 완료 될 때까지 기다리지 않고 모든 작업이 완료된 후에 함수를 실행하려면 group.wait()
대신 notify
함수를 사용하십시오.
group.notify(queue: DispatchQueue.main) { //the queue: parameter is which queue this block will run on, if you need to do UI updates, use the main queue
print("all tasks done!") //this will execute when all tasks have left the group
}
예제 출력 :
starting long running tasks
long task 0 done!
long task 3 done!
long task 1 done!
long task 2 done!
all tasks done!
자세한 정보는 Apple Docs 또는 관련 주제를 참조하십시오.
세마포 파견
DispatchSemaphore는 여러 계산 컨텍스트에서 리소스에 대한 액세스를 제어하는 데 사용할 수있는 전통적인 카운팅 세마포를 효율적으로 구현합니다.
세마포어를 사용할 때의 시나리오는 파일 읽기 / 쓰기를하는 경우, 여러 작업이 동시에 파일을 읽고 쓰려고하는 경우 성능이 향상되어 각 작업이 차례를 기다릴 수 있습니다. I / O 컨트롤러를 과부하시키지 않습니다.
스위프트 3
func do2TasksAtATime () {
print("starting long running tasks (2 at a time)")
let sem = DispatchSemaphore(value: 2) //this semaphore only allows 2 tasks to run at the same time (the resource count)
for i in 0...7 { //launch a bunch of tasks
DispatchQueue.global().async { //run tasks on a background thread
sem.wait() //wait here if no resources available
sleep(2) //do some long task eg file access (here we are just sleeping for a 2 seconds for demonstration purposes)
print("long task \(i) done! \(Date())")
sem.signal() //let the semaphore know this resource is now available
}
}
}
예제 출력 : (타임 스탬프를 주목하십시오)
starting long running tasks (2 at a time)
long task 0 done! 2017-02-16 07:11:53 +0000
long task 1 done! 2017-02-16 07:11:53 +0000
long task 2 done! 2017-02-16 07:11:55 +0000
long task 3 done! 2017-02-16 07:11:55 +0000
long task 5 done! 2017-02-16 07:11:57 +0000
long task 4 done! 2017-02-16 07:11:57 +0000
long task 6 done! 2017-02-16 07:11:59 +0000
long task 7 done! 2017-02-16 07:11:59 +0000
자세한 정보는 Apple Docs를 참조하십시오.
연속 대 동시 발송 대기열
스위프트 3
연속 대기열
func serialQueues () {
let serialQueue = DispatchQueue(label: "com.example.serial") //default queue type is a serial queue
let start = Date ()
for i in 0...3 { //launch a bunch of tasks
serialQueue.async { //run tasks on a background thread, using our serial queue
sleep(2) //do some long task eg webservice or database lookup
let timeTaken = Date().timeIntervalSince(start)
print("serial long task \(i) done! total time taken: \(timeTaken)")
}
}
}
예제 출력 :
serial long task 0 done! total time taken: 2.07241100072861
serial long task 1 done! total time taken: 4.16347700357437
serial long task 2 done! total time taken: 6.23209798336029
serial long task 3 done! total time taken: 8.30682599544525
동시 대기열
func concurrentQueues () {
let concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent) //explicitly specify the queue to be a concurrent queue
let start = Date ()
for i in 0...3 { //launch a bunch of tasks
concurrentQueue.async { //run tasks on a background thread, using our concurrent queue
sleep(2) //do some long task eg webservice or database lookup
let timeTaken = Date().timeIntervalSince(start)
print("concurrent long task \(i) done! total time taken: \(timeTaken)")
}
}
}
예제 출력 :
concurrent long task 3 done! total time taken: 2.07092100381851
concurrent long task 0 done! total time taken: 2.07087397575378
concurrent long task 2 done! total time taken: 2.07086700201035
concurrent long task 1 done! total time taken: 2.07089096307755
토론
위의 예제에서 알 수 있듯이 직렬 대기열은 각 작업을 대기열에 제출 된 순서대로 완료합니다. 각 작업은 이전 작업이 끝나기를 기다렸다가 실행됩니다. 동시 대기열의 경우 각 작업은 대기열의 다른 작업을 대기하지 않고 가능한 한 빨리 실행합니다. 장점은 대기열의 모든 작업이 별도의 스레드에서 동시에 실행되므로 동시 대기열이 직렬 대기열보다 시간이 적게 걸리는 것입니다.
작업 실행 순서가 중요하지 않은 경우 최상의 효율성을 위해 항상 동시 대기열을 사용하십시오.