GCD
async
Swift
queue
Synchronization

GCD(Grand Central Dispatch)でキューの順番とスピードを制御する方法(1/2)

More than 1 year has passed since last update.

Grand Central Dispatch (GCD) とはAppleが用意したマルチタスクを簡単に行うための方法です。簡単にまとめると、タスクをスレッド分けするのが超便利なフレームワークだよ★
タスクが多くなってきて、別スレッドが必要になった時にどちらも有効です。

1. キューとGCDの単語集

キューとは?

同期通信(synchronously)と非同期通信(asynchronously)にタスクがこなせるコードのブロックです。メインスレッドでもサブスレッドでも行える。
キューはデータ項目の先入れ先出し(FIFO: First In/First Out)の仕組みです。

work itemとは?

Dispatch Queueが実行するタスクのことです。Queueの初期化時に作られる場合もあれば、あとでQueueにアサインされるともある。また再利用も可能。

キューはSerial(一列)もしくはConcurrent(コンカレント/並列)にタスクが実行できる。Serial はWork Item(タスク)が終わってからのWork Itemを実行し、ConcurrentはWork Itemが並列に実行される。

Screen Shot 2017-07-11 at 1.23.16 AM.png

2. DispatchQueueでキューを作ってみよう

func simpleQueues(){
      let queue = DispatchQueue(label: "com.ayakosayama.simpleQueue")
        queue.sync {
            for i in 0..<10{
                print("💜",i)
            }
        }

        for i in 100..<110{
            print("💛",i)
        }
}

DispatchQueue(label:)でQueueを初期化する。label:で名前もつけることができる。これを実行すると💜x 10 -> 💛 x 10 の運番で実行される。メインスレッドが同期通信(sync)なので、どちらもメインスレッドで実行されています。(下図1)

3. DispatchQueue()でAsync(非同期通信)をしてみよう

func asyncQueues(){

        let queue = DispatchQueue(label: "com.ayakosayama.myqueue1")
        let queue2 = DispatchQueue(label: "com.ayakosayama.myqueue2")

        queue.async {
            for i in 0..<10{
                print("🔵",i)
            }
        }

        queue2.async {
            for i in 100..<110{
                print("🔴",i)
            }
        }

        for i in 1000..<1010{
            print("⚫️",i)
        }
    }

下図2をみると、タスク三つがほぼ同じスピードで処理されていることがわかります。

Screen Shot 2017-07-11 at 12.02.45 PM.png

4. Quality を変更して処理スピードを制御する

DispatchQueueは "label"の他に"qos"(Quality of Service:処理速度)を決めることができる。こちらのドキュメントによると、QOSは4段階あって、スピードは以下です。

Screen Shot 2017-07-11 at 12.22.34 PM.png

選べないQOSが実は2つほどあり、DefaultとUnspecifiedで、速さは以下です。
Screen Shot 2017-07-11 at 2.09.32 PM.png

前回と同じ赤、青、黒ボールをprintするという3つの処理をしてみましょう。

func queueWithQos(){

        queue.async {
            for i in 0..<10{
                print("🔵",i)
            }
        }

        queue2.async {
            for i in 100..<110{
                print("🔴",i)
            }
        }

        for i in 1000..<1010{
            print("⚫️",i)
        }
}

User-initiated VS Utility

let queue = DispatchQueue(label: "com.ayakosayama.myqueue1", qos: .userInitiated)
let queue2 = DispatchQueue(label: "com.ayakosayama.myqueue2", qos: .utility)

Background vs User-Interactive

let queue = DispatchQueue(label: "com.ayakosayama.myqueue1", qos: .background)
let queue2 = DispatchQueue(label: "com.ayakosayama.myqueue2", qos: .userInteractive)

図3は、⚫️がメインスレッドなので、一番先に処理されて、🔵user-instantiatedの方が、🔴Utilityより処理が早いことがわかります。

図4では、🔴User-interactiveが⚫️メインスレッドとほぼ同じスピードで処理されていることがわかります。🔵Backgroundは何があっても、一番処理が遅いです。

Screen Shot 2017-07-11 at 12.07.50 PM.png

2回目はGCDのGlobal()とDelay()とコールバック関数についてまとめます!

元ネタこちら
Gihtubコードはこちら