수색…


소개

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를 업데이트하려면 메인 대기열에 도착해야합니다.

주 대기열 호출에는 synchronousasynchronous 라는 두 가지 유형이 있습니다. 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

토론

위의 예제에서 알 수 있듯이 직렬 대기열은 각 작업을 대기열에 제출 된 순서대로 완료합니다. 각 작업은 이전 작업이 끝나기를 기다렸다가 실행됩니다. 동시 대기열의 경우 각 작업은 대기열의 다른 작업을 대기하지 않고 가능한 한 빨리 실행합니다. 장점은 대기열의 모든 작업이 별도의 스레드에서 동시에 실행되므로 동시 대기열이 직렬 대기열보다 시간이 적게 걸리는 것입니다.

작업 실행 순서가 중요하지 않은 경우 최상의 효율성을 위해 항상 동시 대기열을 사용하십시오.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow