码迷,mamicode.com
首页 > 其他好文 > 详细

dispatch_after实现原理深度探索

时间:2016-01-04 01:23:32      阅读:1261      评论:0      收藏:0      [点我收藏+]

标签:

dispatch_after 是GCD中延后执行的一种方法,但是实现原理自己并没有仔细探索过,最近在和群里小伙伴讨论GCD的时候说到dispatch_after,讨论的程序有点复杂,我这里简化为一个for循环来阐述具体实现原理。
 
示例程序1
1   // 循环5次
2     for (int i =0; i < 5; i++ ) {
3         
4         NSLog(@"let‘s go %d",i);
5         // 设置2秒后执行block
6         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
7             NSLog(@"This is my %d number!",i);
8         });
9     }
 
程序1运行结果:
 1 2016-01-03 23:55:49.109 dispatchAfterDeep[1095:60579] lets go 0
 2 2016-01-03 23:55:49.110 dispatchAfterDeep[1095:60579] lets go 1
 3 2016-01-03 23:55:49.111 dispatchAfterDeep[1095:60579] lets go 2
 4 2016-01-03 23:55:49.111 dispatchAfterDeep[1095:60579] lets go 3
 5 2016-01-03 23:55:49.111 dispatchAfterDeep[1095:60579] lets go 4
 6 2016-01-03 23:55:51.111 dispatchAfterDeep[1095:60579] This is my 0 number!
 7 2016-01-03 23:55:51.300 dispatchAfterDeep[1095:60579] This is my 1 number!
 8 2016-01-03 23:55:51.301 dispatchAfterDeep[1095:60579] This is my 2 number!
 9 2016-01-03 23:55:51.301 dispatchAfterDeep[1095:60579] This is my 3 number!
10 2016-01-03 23:55:51.301 dispatchAfterDeep[1095:60579] This is my 4 number!
 
我们都知道dispatch_after是异步执行它的Block,但是如何异步执行却不知道,先来看下官方文档是如何描述
Declaration
void dispatch_after( dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block);

Parameters
when    
The temporal milestone returned by dispatch_time or dispatch_walltime.
queue    
The queue on which to submit the block. The queue is retained by the system until the block has run to completion. This parameter cannot be NULL.
block    
The block to submit. This function performs a Block_copy and Block_release on behalf of the caller. This parameter cannot be NULL.

Discussion
This function waits until the specified time and then asynchronously adds block to the specified queue.

 

官方文档描述很简洁,翻译过来就是:这个函数等到特定的时间,然后异步添加block到指定的队列中;在示例程序1里面,指定的队列是主队列,也就是当进入循环的时候,会先执行打印了lets go语句,然后异步执行dispatch_after函数,由于内部使用变量来计时,所以“定时器”是设置在了主线程上,等待2秒然后开子线程将Block加入到主队列中,最后主队列按顺序执行Block,但是这样正确吗?

把示例程序的循环次数加到1000次就会发现,Block依然是按顺序执行,但是异步添加Block到主队列肯定不会按顺序添加,主队列又是顺序执行,那么一定会有顺序错误的打印出现,可是继续增加到10000次还是按顺序执行,那么这里dispatch_after函数可能是将添加Block的操作放入一个串行队列,然后在子线程上执行队列,将BLock添加到主队列中,最后主队列执行Block操作。
 
添加Block部分伪代码如下
1 delay (2){
2 
3         dispatch_async(DISPATCH_QUEUE_SERIAL, ^{
4 
5             (add block into main queue);
6 
7         });
8     }
 
因为GCD底部细节无法查看,只能逻辑上推断,目前使用以上推断可以顺利解释问题,自己也和小伙伴探讨了很久才确定以上推断,如果有新的发现欢迎交流。
   }

dispatch_after实现原理深度探索

标签:

原文地址:http://www.cnblogs.com/Voodoodong/p/5097534.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!