[Swift] GCDの種類と使い方

GCDはSwiftでスレッドプログラミングする時には避けて通れない道です。
これを使いこなせれば大抵のスレッド処理は賄えると思います。

以下の3パターンがあります。

  • メインキュー (メインスレッドで行われる)
  • グローバルキュー (別のスレッドでよろしく処理される)
  • プライベートキュー (自分で作成したキューで処理する)

メインキュー

メインスレッドで処理される。
UIの更新とかはこのスレッドで行わないとエラーになる。

1
2
3
4
5
6
7
8
9
10
11
12
13
// キューの取得
let mainQueue = DispatchQueue.main
 
// EXC_BAD_INSTRUCTION になる
// おそらく、MainスレッドからsyncでCallしたため、デッドロック
// mainQueue.sync {
//     print("Hello! sync MainQueue")
// }
 
// 非同期で実行(おそらくこの処理が終わってからCallされる
mainQueue.async {
    print("Hello! async MainQueue")
}

グローバルキュー

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// キューの取得
let globalQueue = DispatchQueue.global(qos: .default)
 
var greet = ""
 
// 同期的に処理
globalQueue.sync {
    greet = "Hello!"
    print("\(greet) Grobal Sync Queue")
}
 
// syncは同期的に処理されるので、スレッド処理の下で値にアクセスする事ができる
print("\(greet) grobalQueueSample")
 
// 非同期に処理
globalQueue.async {
    print("\(greet) Grobal Async Queue")
}

プライベートキュー

自分で作成するキューは並列処理するキューと逐次処理するキューを作成できる。
(作成時のパラメーターで振る舞いが変わる)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 非同期的なプライベートキューを作成
// 非同期なので、タスクは並列に処理される
let concurrentPrivateQueue_: DispatchQueue = DispatchQueue(label: "ConcurrentQueue", qos: .userInteractive, attributes:.concurrent)
 
// 逐次処理するくキュー
// 処理が終わってから次の処理を行う
let oneByOnePrivateQueue_: DispatchQueue = DispatchQueue(label: "OneByOne", qos: .userInteractive, attributes:.initiallyInactive)
 
// テスト用の実行関数
func useQueue(label: String, queue: DispatchQueue) {
    queue.async {
        for i in 1...10 {
            print("\(label) First \(i)")
        }
    }
    queue.async {
        for i in 1...10 {
            print("\(label) Second \(i)")
        }
    }
    queue.async {
        for i in 1...10 {
            print("\(label) Third \(i)")
        }
    }
}
 
// キューを使うサンプル
func privateQueueSample() {
    // 逐次処理は開始しないと処理が実行されない
    oneByOnePrivateQueue_.activate()
    useQueue(label: "OneByOne", queue: oneByOnePrivateQueue_)
 
    useQueue(label: "Concurrent", queue: concurrentPrivateQueue_)
}
 
privateQueueSample()

参考URL

0 件のコメント :

コメントを投稿