サーチ…


前書き

Grand Central Dispatch(GCD)はマルチスレッドに対するアップルの答えです。キュー内で同期または非同期にタスクを実行するための軽量フレームワークで、バックグラウンドでCPUスレッドを処理します。

関連トピック: 同時実行性

ディスパッチキューを作成する

dispatch_queue_createを使用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を更新するには、メインキューにNSURLSessionする必要があります

メイン・キュー・コールには、 synchronousasynchronous型の2種類がありasynchronoussynchronouslyに何かを呼び出すと、その操作を開始したスレッドは、タスクが完了するのを待ってから続行します。 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は、作業の集約を可能にします。それらを使用して、複数の異なる作業項目を提出し、異なるキューで実行する可能性がある場合でも、完了した時点を追跡できます。この動作は、すべての指定されたタスクが完了するまで進行できない場合に役立ちます。

これが役に立つ場合のシナリオは、続行する前に完了する必要のある複数のWebサービス呼び出しがある場合です。たとえば、いくつかの関数で処理する必要がある複数のデータセットをダウンロードする必要があります。受信したすべてのデータを処理する関数を呼び出す前に、すべてのWebサービスが完了するまで待つ必要があります。

スウィフト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.wait()

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