GCDでちょっと遊ぶ
バックグラウンドスレッドに非同期で実行したい処理を投げる
memo
dispatch_async(タスクを入れるキュー, ^{
// タスクの処理内容を表すブロック
});
例
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(globalQueue, ^{ sleep(10); NSLog(@"thread label %s", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)); }); NSLog(@"thread label %s", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL));
2017-08-24 22:15:24.552 TestApp[56964:5152615] thread label com.apple.main-thread 2017-08-24 22:15:34.556 TestApp[56964:5152686] thread label com.apple.root.default-qos
バックグラウンドスレッドに同期実行したい処理を投げる
memo
dispatch_sync(タスクを入れるキュー, ^{
// タスクの処理内容を表すブロック
});
例
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_sync(globalQueue, ^{ sleep(10); NSLog(@"thread label %s", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)); }); NSLog(@"thread label %s", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL));
2017-08-24 22:18:05.450 TestApp[57017:5156204] thread label com.apple.root.default-qos 2017-08-24 22:18:05.450 TestApp[57017:5156204] thread label com.apple.main-thread
タスクを並行に実行させる
memo
// 2つ目の引数でConcurrentキュー を生成するぞ、という指定 dispatch_queue_t concurrentQueue = dispatch_queue_create("com.exmaple.gcd.MyConcurrentDispatchQueue", DISPATCH_QUEUE_CONCURRENT);
Concurrentキュー を利用する。
例
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.exmaple.gcd.MyConcurrentDispatchQueue", DISPATCH_QUEUE_CONCURRENT); for (int i = 0; i < 10; i++) { dispatch_async(cuncurrentQueue, ^{ sleep(rand() % 10 + 1); NSLog(@"thread label %s - %i", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), i); }); }
2017-08-24 22:30:49.667 TestApp[57252:5175489] thread label com.exmaple.gcd.MyConcurrentDispatchQueue - 5 2017-08-24 22:30:51.667 TestApp[57252:5175490] thread label com.exmaple.gcd.MyConcurrentDispatchQueue - 6 2017-08-24 22:30:52.664 TestApp[57252:5175276] thread label com.exmaple.gcd.MyConcurrentDispatchQueue - 3 2017-08-24 22:30:52.664 TestApp[57252:5175494] thread label com.exmaple.gcd.MyConcurrentDispatchQueue - 9 2017-08-24 22:30:53.667 TestApp[57252:5175491] thread label com.exmaple.gcd.MyConcurrentDispatchQueue - 7 2017-08-24 22:30:56.667 TestApp[57252:5175269] thread label com.exmaple.gcd.MyConcurrentDispatchQueue - 1 2017-08-24 22:30:56.667 TestApp[57252:5175267] thread label com.exmaple.gcd.MyConcurrentDispatchQueue - 0 2017-08-24 22:30:57.667 TestApp[57252:5175488] thread label com.exmaple.gcd.MyConcurrentDispatchQueue - 4 2017-08-24 22:30:57.667 TestApp[57252:5175493] thread label com.exmaple.gcd.MyConcurrentDispatchQueue - 8 2017-08-24 22:30:58.662 TestApp[57252:5175271] thread label com.exmaple.gcd.MyConcurrentDispatchQueue - 2
タスクを直列に実行させる
memo
// 2つ目の引数でSerialキュー を生成するぞ、という指定 dispatch_queue_t serialQueue = dispatch_queue_create("com.exmaple.gcd.MySerialDispatchQueue", DISPATCH_QUEUE_SERIAL); // DISPATCH_QUEUE_SERIAL は NULL. /*! * @const DISPATCH_QUEUE_SERIAL * * @discussion A dispatch queue that invokes blocks serially in FIFO order. */ #define DISPATCH_QUEUE_SERIAL NULL
Serialキュー を利用する。
例
dispatch_queue_t serialQueue = dispatch_queue_create("com.exmaple.gcd.MySerialDispatchQueue", DISPATCH_QUEUE_SERIAL); for (int i = 0; i < 10; i++) { dispatch_async(serialQueue, ^{ sleep(rand() % 10 + 1); NSLog(@"thread label %s - %i", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), i); }); }
2017-08-24 22:37:00.679 TestApp[57358:5185254] thread label com.exmaple.gcd.MySerialDispatchQueue - 0 2017-08-24 22:37:10.679 TestApp[57358:5185254] thread label com.exmaple.gcd.MySerialDispatchQueue - 1 2017-08-24 22:37:14.684 TestApp[57358:5185254] thread label com.exmaple.gcd.MySerialDispatchQueue - 2 2017-08-24 22:37:23.685 TestApp[57358:5185254] thread label com.exmaple.gcd.MySerialDispatchQueue - 3 2017-08-24 22:37:24.689 TestApp[57358:5185254] thread label com.exmaple.gcd.MySerialDispatchQueue - 4 2017-08-24 22:37:27.693 TestApp[57358:5185254] thread label com.exmaple.gcd.MySerialDispatchQueue - 5 2017-08-24 22:37:32.696 TestApp[57358:5185254] thread label com.exmaple.gcd.MySerialDispatchQueue - 6 2017-08-24 22:37:41.700 TestApp[57358:5185254] thread label com.exmaple.gcd.MySerialDispatchQueue - 7 2017-08-24 22:37:45.702 TestApp[57358:5185254] thread label com.exmaple.gcd.MySerialDispatchQueue - 8 2017-08-24 22:37:55.706 TestApp[57358:5185254] thread label com.exmaple.gcd.MySerialDispatchQueue - 9
dispatch_get_global_queue と dispatch_queue_create の違い
- dispatch_get_main_queue / dispatch_get_global_queue
- システムが用意している既存のキューがいくつかあるのでそれを取得する。Main Dispatch Queue以外はConcurrentキュー
- dispatch_queue_create
- 自作のキュー。二つ目の引数でConcurrent/Serialキューのどちらかを決める
指定した時間の後に処理を実行したい
Handler#postDelay
的な。
memo
dispatch_time_t
dispath_after
の二つを使う。
書き方
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC); dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_after(time, globalQueue, ^{ NSLog(@"thread label %s", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)); }); NSLog(@"thread label %s", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL));
2017-08-24 22:55:03.519 TestApp[57464:5205849] thread label com.apple.main-thread 2017-08-24 22:55:08.519 TestApp[57464:5205963] thread label com.apple.root.default-qos
全てのキューの処理が終わったら任意の処理を行う
memo
dispatch_group_t
dispatch_group_async
dispatch_group_wait
の3つを使う。あまり書いたことないですがやりたいことはjoinに近い?
書き方
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); dispatch_group_t another_group = dispatch_group_create(); dispatch_group_async(another_group, globalQueue, ^{ NSLog(@"thread label %s - task 1 start", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)); sleep(rand() % 10 + 15); NSLog(@"thread label %s - task 1 end", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)); }); dispatch_group_async(group, globalQueue, ^{ NSLog(@"thread label %s - task 2 start", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)); sleep(rand() % 10 + 1); NSLog(@"thread label %s - task 2 end", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)); }); dispatch_group_async(group, globalQueue, ^{ NSLog(@"thread label %s - task 3 start", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)); sleep(rand() % 10 + 1); NSLog(@"thread label %s - task 3 end", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)); }); dispatch_group_async(group, globalQueue, ^{ NSLog(@"thread label %s - task 4 start", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)); sleep(rand() % 10 + 1); NSLog(@"thread label %s - task 4 end", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)); }); NSLog(@"before dispatch_group_wait - group"); dispatch_group_wait(group, DISPATCH_TIME_FOREVER); NSLog(@"after dispatch_group_wait - group"); NSLog(@"before dispatch_group_wait - another_group"); dispatch_group_wait(another_group, DISPATCH_TIME_FOREVER); NSLog(@"after dispatch_group_wait - another_group"); NSLog(@"thread label %s", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL));
2017-08-24 23:03:42.995 TestApp[57690:5218146] thread label com.apple.root.default-qos - task 1 start 2017-08-24 23:03:42.995 TestApp[57690:5218151] thread label com.apple.root.default-qos - task 2 start 2017-08-24 23:03:42.995 TestApp[57690:5218143] thread label com.apple.root.default-qos - task 3 start 2017-08-24 23:03:42.995 TestApp[57690:5218149] thread label com.apple.root.default-qos - task 4 start 2017-08-24 23:03:42.995 TestApp[57690:5218087] before dispatch_group_wait - group 2017-08-24 23:03:47.000 TestApp[57690:5218143] thread label com.apple.root.default-qos - task 3 end 2017-08-24 23:03:51.997 TestApp[57690:5218149] thread label com.apple.root.default-qos - task 4 end 2017-08-24 23:03:52.997 TestApp[57690:5218151] thread label com.apple.root.default-qos - task 2 end 2017-08-24 23:03:52.998 TestApp[57690:5218087] after dispatch_group_wait - group // groupのキューに追加した task 3, 4, 2を待つ 2017-08-24 23:03:52.998 TestApp[57690:5218087] before dispatch_group_wait - another_group 2017-08-24 23:04:04.997 TestApp[57690:5218146] thread label com.apple.root.default-qos - task 1 end 2017-08-24 23:04:04.997 TestApp[57690:5218087] after dispatch_group_wait - another_group // another_groupのキューに追加した task 1を待つ 2017-08-24 23:04:04.998 TestApp[57690:5218087] thread label com.apple.main-thread
セマフォについてはまた明日。。
参考
- http://dev.classmethod.jp/smartphone/iphone/swift-3-how-to-use-gcd-api-1/
- http://d.hatena.ne.jp/shu223/20121003/1354425848
エキスパートObjective-Cプログラミング ?iOS/OS Xのメモリ管理とマルチスレッド?
- 作者: 坂本一樹
- 出版社/メーカー: インプレス
- 発売日: 2011/11/18
- メディア: 単行本(ソフトカバー)
- 購入: 8人 クリック: 343回
- この商品を含むブログ (25件) を見る