GCD使用与技巧(续)
2016-03-09 17:56
211 查看
后台执行 , 前台执行
// 前台执行 dispatch_async(dispatch_get_main_queue(), ^{ // do something }); // 后台执行 dispatch_async(dispatch_get_global_queue(0, 0), ^{ // do something });
dispatch_once_t必须是全局或static变量 毕竟非全局或非static的dispatch_once_t变量在使用时会导致非常不好排查的bug
// 一次执行, 只执行一次 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // 单例 });
dispatch_queue_create,创建队列用的,它的参数只有两个, 而dispatch_queue_attr_t类型是有已经定义好的常量
// 串行 dispatch_queue_t queueSerial = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL); // 并行 dispatch_queue_t queueComcurrent = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);
dispatch_after
// 创建串行队列 dispatch_queue_t queue = dispatch_queue_create("myQueueSerial", DISPATCH_QUEUE_SERIAL); // 打印第一条数据 NSLog(@"begin add block join in ..."); // 提交一个block // 异步执行 dispatch_async(queue, ^{ // sleep 10s [NSThread sleepForTimeInterval:10]; NSLog(@"sleep block done .... "); }); // 5s 以后调教block dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"after block done ..."); });
结果输出 2016-03-09 16:51:32.382 PopView[3310:237164] begin add block join in ... 2016-03-09 16:51:37.383 PopView[3310:237164] after block done ... 2016-03-09 16:51:42.383 PopView[3310:237293] sleep block done ....
dispatch_time_t正确创建姿势
用dispatch_after的时候就会用到dispatch_time_t变量, 如何创建合适的时间/**
* @param when 第一个参数一般是 DISPATCH_TIME_NOW,表示从现在开始
* @param delta delta 纳秒
*/
* 延时一秒可以这样
* dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC);
* dispatch_time(DISPATCH_TIME_NOW, 1000 * USEC_PER_SEC);
* dispatch_time(DISPATCH_TIME_NOW, USEC_PER_SEC * NSEC_PER_USEC); — 每秒的毫秒数乘以每毫秒的纳秒数
//原型 dispatch_time_t dispatch_time ( dispatch_time_t when, int64_t delta );
dispatch_suspend, dispatch_resume: 提供挂起、恢复”队列的功能
dispatch_queue_t queueTest = dispatch_queue_create("test.gcd", DISPATCH_QUEUE_SERIAL); //提交第一个block,延时5秒打印。 dispatch_async(queueTest, ^{ [NSThread sleepForTimeInterval:5]; NSLog(@"After 5 seconds..."); }); //提交第二个block,也是延时5秒打印 dispatch_async(queueTest, ^{ [NSThread sleepForTimeInterval:5]; NSLog(@"After 5 seconds again..."); }); //延时一秒 NSLog(@"sleep 1 second..."); [NSThread sleepForTimeInterval:1]; //挂起队列 NSLog(@"suspend..."); dispatch_suspend(queueTest); //延时10秒 [NSThread sleepForTimeInterval:10]; NSLog(@"sleep 10 second..."); //恢复队列 dispatch_resume(queueTest); NSLog(@"resume...");
2016-03-09 17:11:19.401 PopView[3430:251221] sleep 1 second... 2016-03-09 17:11:20.402 PopView[3430:251221] suspend... 2016-03-09 17:11:24.405 PopView[3430:251253] After 5 seconds... 2016-03-09 17:11:30.404 PopView[3430:251221] sleep 10 second... 2016-03-09 17:11:30.404 PopView[3430:251221] resume... 2016-03-09 17:11:35.409 PopView[3430:251253] After 5 seconds again...
dispatch_apply
dispatch_queue_t queue = dispatch_queue_create("queue-", DISPATCH_QUEUE_SERIAL); // 执行5次 dispatch_apply(3, queue, ^(size_t i) { NSLog(@"apply loop: %zu", i); }); NSLog(@"after apply");
// 明明是异步, 却最后打印如下, dispatch_apply将外面的线程(main线程)“阻塞”了! // 2016-03-09 17:19:32.628 PopView[3474:255956] apply loop: 0 // 2016-03-09 17:19:32.628 PopView[3474:255956] apply loop: 1 // 2016-03-09 17:19:32.628 PopView[3474:255956] apply loop: 2 // 2016-03-09 17:19:32.628 PopView[3474:255956] after apply
出现死锁的情况
// 情况一 - (void)updateUI1 { dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"Update ui 1"); //死锁! [self updateUI2]; }); } - (void)updateUI2 { dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"Update ui 2"); }); }
dispatch_queue_t queue11 = dispatch_queue_create("test.gcd", DISPATCH_QUEUE_SERIAL); dispatch_apply(3, queue, ^(size_t i) { NSLog(@"apply loop: %zu", i); //再来一个dispatch_apply!死锁! dispatch_apply(3, queue, ^(size_t j) { NSLog(@"apply loop inside %zu", j); }); }); // 这端代码只会输出“apply loop: 1”。。。就没有然后了 O.o --- 避免dispatch_apply的嵌套调用
dispatch_group_t
dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue, ^{ // Do your something }); // 当你无法直接使用队列变量时,就无法使用dispatch_group_async了,下面以使用AFNetworking时的情况: AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; //Enter group dispatch_group_enter(group); [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { //Deal with result... //Leave group dispatch_group_leave(group); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { //Deal with error... //Leave group dispatch_group_leave(group); }]; //More request... // 使用dispatch_group_enter,dispatch_group_leave就可以很方便处理
文章参照 : http://www.cocoachina.com/ios/20150505/11751.html
相关文章推荐
- openGL之光照2(材料、颜色追踪、光源)---openGL学习笔记(十)
- GIT和SVN之间的五个基本区别
- 如何在CentOS7上改变网络接口名
- IOS8 IOS9 高德地图弹出是否允许定位框功能代码
- java学习之文件的删除
- 设计模式之工厂模式探讨
- erlang怎样有效监听大量并发连接
- 使用 Subversion (SVN) 的方式来访问 Github
- hdu1087最大流
- unity3d调用jar类中的方法和属性
- UI学习第08天
- Hello world S.B.S.
- grep检索文本
- 高项3.7日第一次课,第一章信息化基础知识与第二章信息系统服务管理要点梳理
- Oracle特殊字段处理--工作备忘2016/03/09
- 给select添加自定义值和选项
- Newtonsoft.Json.dll 中的序列化与反序列化
- Android 的 分发机制
- jersey spring shiro mybatis mysql集成配置
- socket