GCDのDispatch Queue(シリアルキュー、コンカレントキュー、ホームキュー)
10904 ワード
まず歩く少年郎が書いた「iOSマルチスレッド--マルチスレッドを徹底的にマスターする『GCD』」に感謝します.それは私にGCDの多くの概念をはっきり理解させました.今は印象を深めるために、自分でもう1部ノートを書くつもりです.
1、キュー
Serial Dispatch Queue(シリアルキュー):実行中の処理が終了するのを待って、次の処理を実行します. Concurrent Dispatch Queue(コンカレントキュー):現在実行中の処理が終了するのを待たずに、次の処理を続行します.非同期実行でのみ、同時性を実現できます.
シリアル・キューの作成:
同時キューの作成:
2、任務
は同期して実行される.新しいスレッドを開かない は非同期で実行されます.新しいスレッド を開く
同期実行:
非同期実行:
もう一つの違いは、同期キューは、タスクをキューに追加した後、すぐに実行することです.同時キューではありません.これは4,GCDの具体的な使用に反映される.
シリアルキュー+同期実行 シリアルキュー+非同期実行 同時キュー+同期実行 同時キュー+非同期実行 ホームキュー+同期実行 ホームキュー+非同期実行 補足:プライマリ・キューはシリアル・キューに属しますが、特殊性のため個別に列されます.
4、GCDの具体的な使用
は同期実行であるため、新しいスレッドは作成されず、メインスレッドで実行される. はシリアルキューであるため、キューのタスクが次々と実行される. すべてのタスクが
出力結果分析:は非同期実行であるため、新しいスレッドが作成される. はシリアルキューであるため、キュー内のタスクが次々と実行される. は、すべてのキュータスクが
出力結果分析:同期実行であるため、新しいスレッドは作成されず、メインスレッドで実行される. はコンカレントキューであるが、同期実行であるため、コンカレント性は現れず、タスクは次々と実行される. すべてのタスクが
出力結果分析:非同期実行のため、新しいスレッドが作成されました. 同時キューのため、非同期実行時にその同時性が現れ、タスク間で交互に同時に実行される. は、すべてのキュータスクが
出力結果分析:は1つの文しか出力されず、その後の文は実行されません. プライマリ・キューは、プライマリ・スレッドのキューです. デッドロック発生:同期実行は、すぐに実行されることを知っています(シリアルキュー同期実行と同時キュー同期実行の結果分析第3条を参照).しかし、現在のメインスレッドが実行しているタスクは
別のスレッドで呼び出せばいいので、シリアルキュー+非同期実行で新しいスレッドを作成します.
出力結果解析:プライマリ・キューはシリアル・キューの一種であるため、シリアル・キューの解析にも適用されます.は同期実行であるため、新しいスレッドは作成されず、メインスレッドで実行される. はシリアルキューであるため、キューのタスクが次々と実行される. すべてのタスクが
出力結果分析:は非同期実行であり、新しいスレッドを開くことができるが、プライマリ・キュー列であるため、プライマリ・スレッドでのみ実行される.(この点は通常のシリアルキューとは異なる) メインキューは特殊なシリアルキューであるため、キューのタスクは次々と実行される. は、すべてのキュータスクが
(1)キューを作成することとスレッドを作成することは2つあります.(2)1つのスレッド内に複数のキューがあり,シリアルキューとパラレルキューが混在している可能性がある.(3)キューが同期実行であるか非同期実行であるかによって、新しいスレッドを作成するかどうか.(4)デッドロックの問題.
1、キュー
キューは2種類のみです.
シリアル・キューの作成:
dispatch_queue_t serialQueue = dispatch_queue_create(" ", NULL);
//
dispatch_queue_t serialQueue = dispatch_queue_create(" ", DISPATCH_QUQUE_SERIAL);
同時キューの作成:
dispatch_queue_t concurrentQueue = dispatch_queue_create(" ", DISPATCH_QUQUE_CONCURRENT);
2、任務
タスクを実行する方法は2つしかありません.
同期実行:
dispatch_sync(queue, ^{ ... });
非同期実行:
dispatch_async(queue, ^{ ... });
もう一つの違いは、同期キューは、タスクをキューに追加した後、すぐに実行することです.同時キューではありません.これは4,GCDの具体的な使用に反映される.
3、GCDを使うのはキュー+タスク
4、GCDの具体的な使用
(1)シリアルキュー+同期実行
- (void) KSserialQueueSync {
NSLog(@"test start");
dispatch_queue_t serialQueue = dispatch_queue_create("com.ks.serialQueue", NULL);
dispatch_sync(serialQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block1 %@", [NSThread currentThread]);
}
});
dispatch_sync(serialQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block2 %@", [NSThread currentThread]);
}
});
dispatch_sync(serialQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block3 %@", [NSThread currentThread]);
}
});
NSLog(@"test over");
}
[915:40526] test start
[915:40526] block1 {number = 1, name = main}
[915:40526] block1 {number = 1, name = main}
[915:40526] block2 {number = 1, name = main}
[915:40526] block2 {number = 1, name = main}
[915:40526] block3 {number = 1, name = main}
[915:40526] block3 {number = 1, name = main}
[915:40526] test over
出力結果分析:
- (void) KSserialQueueSync {
NSLog(@"test start");
dispatch_queue_t serialQueue = dispatch_queue_create("com.ks.serialQueue", NULL);
dispatch_sync(serialQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block1 %@", [NSThread currentThread]);
}
});
dispatch_sync(serialQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block2 %@", [NSThread currentThread]);
}
});
dispatch_sync(serialQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block3 %@", [NSThread currentThread]);
}
});
NSLog(@"test over");
}
[915:40526] test start
[915:40526] block1 {number = 1, name = main}
[915:40526] block1 {number = 1, name = main}
[915:40526] block2 {number = 1, name = main}
[915:40526] block2 {number = 1, name = main}
[915:40526] block3 {number = 1, name = main}
[915:40526] block3 {number = 1, name = main}
[915:40526] test over
test start
とtest over
の間で実行されるため、タスクがキューに入るとすぐに実行されることを示します.(2)シリアルキュー+非同期実行
- (void)KSserialQueueAsync {
NSLog(@"test start");
dispatch_queue_t serialQueue = dispatch_queue_create("com.ks.serialQueue", NULL);
dispatch_async(serialQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block1 %@", [NSThread currentThread]);
}
});
dispatch_async(serialQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block2 %@", [NSThread currentThread]);
}
});
dispatch_async(serialQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block3 %@", [NSThread currentThread]);
}
});
NSLog(@"test over");
}
[941:46623] test start
[941:46623] test over
[941:46686] block1 {number = 2, name = (null)}
[941:46686] block1 {number = 2, name = (null)}
[941:46686] block2 {number = 2, name = (null)}
[941:46686] block2 {number = 2, name = (null)}
[941:46686] block3 {number = 2, name = (null)}
[941:46686] block3 {number = 2, name = (null)}
出力結果分析:
test start
およびtest over
の後に実行されるため、タスクがキューに追加された直後に実行されるのではなく、すべてのタスクがキューに追加された後に実行されることを示す.(3)同時キュー+同期実行
- (void)KSconcurrentQueueSync {
NSLog(@"test start");
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.ks.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(concurrentQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block1 %@", [NSThread currentThread]);
}
});
dispatch_sync(concurrentQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block2 %@", [NSThread currentThread]);
}
});
dispatch_sync(concurrentQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block3 %@", [NSThread currentThread]);
}
});
NSLog(@"test over");
}
[1001:58076] test start
[1001:58076] block1 {number = 1, name = main}
[1001:58076] block1 {number = 1, name = main}
[1001:58076] block2 {number = 1, name = main}
[1001:58076] block2 {number = 1, name = main}
[1001:58076] block3 {number = 1, name = main}
[1001:58076] block3 {number = 1, name = main}
[1001:58076] test over
出力結果分析:
test start
とtest over
の間で実行されるため、タスクがキューに入るとすぐに実行されることを示します.(4)同時キュー+非同期実行
- (void)KSconcurrentQueueAsync {
NSLog(@"test start");
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.ks.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block1 %@", [NSThread currentThread]);
}
});
dispatch_async(concurrentQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block2 %@", [NSThread currentThread]);
}
});
dispatch_async(concurrentQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block3 %@", [NSThread currentThread]);
}
});
NSLog(@"test over");
}
[1042:64557] test start
[1042:64557] test over
[1042:64615] block3 {number = 4, name = (null)}
[1042:64618] block2 {number = 3, name = (null)}
[1042:64640] block1 {number = 2, name = (null)}
[1042:64615] block3 {number = 4, name = (null)}
[1042:64618] block2 {number = 3, name = (null)}
[1042:64640] block1 {number = 2, name = (null)}
出力結果分析:
test start
およびtest over
の後に実行されるため、タスクがキューに追加された直後に実行されるのではなく、すべてのタスクがキューに追加された後に実行されることを示す.(5)メインキュー+同期実行
- (void)KSmainQueueSync {
NSLog(@"test start");
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_sync(mainQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block1 %@", [NSThread currentThread]);
}
});
dispatch_sync(mainQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block2 %@", [NSThread currentThread]);
}
});
dispatch_sync(mainQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block3 %@", [NSThread currentThread]);
}
});
NSLog(@"test over");
}
[1084:70872] test start
出力結果分析:
KSmainQueueSync
というメソッドなので、このメソッドの実行が完了するのを待つ必要があります.しかし、KSmainQueueSync
この方法は、最初の2番目の3番目のタスクが完了するのを待つ.互いに待ち合ってデッドロックを起こす.別のスレッドで呼び出せばいいので、シリアルキュー+非同期実行で新しいスレッドを作成します.
dispatch_queue_t queue = dispatch_queue_create("com.ks.serialQueue", NULL);
dispatch_async(queue, ^{
[self KSmainQueueSync];
});
[1097:77638] test start
[1097:77593] block1 {number = 1, name = main}
[1097:77593] block1 {number = 1, name = main}
[1097:77593] block2 {number = 1, name = main}
[1097:77593] block2 {number = 1, name = main}
[1097:77593] block3 {number = 1, name = main}
[1097:77593] block3 {number = 1, name = main}
[1097:77638] test over
出力結果解析:プライマリ・キューはシリアル・キューの一種であるため、シリアル・キューの解析にも適用されます.
test start
とtest over
の間で実行されるため、タスクがキューに入るとすぐに実行されることを示します.(6)主行列+非同期実行
- (void)KSmainQueueAsync {
NSLog(@"test start");
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block1 %@", [NSThread currentThread]);
}
});
dispatch_async(mainQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block2 %@", [NSThread currentThread]);
}
});
dispatch_async(mainQueue, ^{
for (int i = 0; i < 2; i++) {
NSLog(@"block3 %@", [NSThread currentThread]);
}
});
NSLog(@"test over");
}
[1130:84261] test start
[1130:84261] test over
[1130:84261] block1 {number = 1, name = main}
[1130:84261] block1 {number = 1, name = main}
[1130:84261] block2 {number = 1, name = main}
[1130:84261] block2 {number = 1, name = main}
[1130:84261] block3 {number = 1, name = main}
[1130:84261] block3 {number = 1, name = main}
出力結果分析:
test start
およびtest over
の後に実行されるため、タスクがキューに追加された直後に実行されるのではなく、すべてのタスクがキューに追加された後に実行されることを示す.(1)キューを作成することとスレッドを作成することは2つあります.(2)1つのスレッド内に複数のキューがあり,シリアルキューとパラレルキューが混在している可能性がある.(3)キューが同期実行であるか非同期実行であるかによって、新しいスレッドを作成するかどうか.(4)デッドロックの問題.