GCD
队列:
dispatch_queue_t
串行队列: 队列中的任务只会顺序执行;
并行队列: 队列中的任务通常会并发执行.
操作:
dispatch_async 异步操作,会并发执行,无法确定任务的执行顺序;
dispatch_sync 同步操作,会依次顺序执行,能够决定任务的执行顺序. //最好不要用 他是同步先执行完这个,才执行其他,导致页面卡死。
dispatch_async(dispatch_queue_t queue, dispatch_block_t block); //async表明异步运行,block代表的是你要做的事情,queue则是你把任务交给谁来处理了.
一.Dispatch Queue
Dispatch Queue是一个任务执行队列,可以让你异步或同步地执行多个Block或函数。Dispatch Queue是FIFO的,即先入队的任务总会先执行。目前有三种类型的Dispath Queue:
1.串行队列(Serial dispatch queue)
2.并发队列(Concurrent dispatch queue)
3.主队列(Main dispatch queue)
看例子:
- (IBAction)touchup:(id)sender { // dispatch_queue_t myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//并行 结果与下列两种相反。 dispatch_queue_t myQueue = dispatch_queue_create("com.queue", DISPATCH_QUEUE_CONCURRENT); //并行 结果与下列两种相反。 // dispatch_queue_t myQueue = dispatch_queue_create("com.queue", NULL); //顺序执行 NULL的时候默认是顺序执行 // dispatch_queue_t myQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL); //顺序执行 顺序执行最好用这两种 不要用sync,会造成页面卡死。 dispatch_async(myQueue, ^{ [NSThread sleepForTimeInterval:6]; NSLog(@"[NSThread sleepForTimeInterval:6];"); }); dispatch_async(myQueue, ^{ [NSThread sleepForTimeInterval:3]; NSLog(@"[NSThread sleepForTimeInterval:3];"); }); dispatch_async(myQueue, ^{ [NSThread sleepForTimeInterval:1]; NSLog(@"[NSThread sleepForTimeInterval:1];"); }); }
总结:串行队列一次只能处理一个任务,可以由用户调用dispatch_queue_create创建。dispatch_queue_create第一个参数是串行队列标识,一般用反转域名的格式表示以防冲突;第二个参数是queue的类型,设为NULL时默认是DISPATCH_QUEUE_SERIAL,将创建串行队列,在必要情况下,你可以将其设置为DISPATCH_QUEUE_CONCURRENT来创建自定义并行队列。
并行队列可以同时处理多个任务,在不得以的情况下可以用dispatch_queue_create创建,但一般我们都要用系统预定义的并行队列,即全局队列(Global Concurrent Dispatch Queues)。
提示:
不建议使用不同优先级的队列,因为如果设计不当,可能会出现优先级反转,即低优先级的操作阻塞高优先级的操作.
二.Dispatch Group
dispatch_group_async可以实现监听一组任务是否完成,完成后得到通知执行其他的操作。这个方法很有用,比如你执行三个下载任务,当三个任务都下载完成后你才通知界面说完成的了。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:6]; NSLog(@"group1 [NSThread sleepForTimeInterval:6];"); }); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:3]; NSLog(@"group2 [NSThread sleepForTimeInterval:3];"); }); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:1]; NSLog(@"group3 [NSThread sleepForTimeInterval:1];"); }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"main thread."); });
dispatch_group_async只会监听最终的结果完成后,并通知main queue
三.dispatch_barrier_async
dispatch_barrier_async是在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行,常用于读写的数据同步操作。
- (IBAction)clickBarrier:(id)sender { // dispatch_queue_t myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //并行执行 dispatch_queue_t myQueue = dispatch_queue_create("com.queue", DISPATCH_QUEUE_CONCURRENT); //先执行前两项,之后再往下并行执行。 dispatch_async(myQueue, ^{ [NSThread sleepForTimeInterval:6]; NSLog(@"[NSThread sleepForTimeInterval:6];"); }); dispatch_async(myQueue, ^{ [NSThread sleepForTimeInterval:3]; NSLog(@"[NSThread sleepForTimeInterval:3];"); }); dispatch_barrier_async(myQueue, ^{ NSLog(@"并行执行"); }); dispatch_async(myQueue, ^{ [NSThread sleepForTimeInterval:3]; NSLog(@"[NSThread sleepForTimeInterval:3];"); }); dispatch_async(myQueue, ^{ [NSThread sleepForTimeInterval:1]; NSLog(@"[NSThread sleepForTimeInterval:1];"); }); } /*打印结果 2015-05-21 14:32:11.898 queueDemo[1870:101851] [NSThread sleepForTimeInterval:3]; 2015-05-21 14:32:14.897 queueDemo[1870:101850] [NSThread sleepForTimeInterval:6]; 2015-05-21 14:32:14.897 queueDemo[1870:101850] 并行执行 2015-05-21 14:32:15.901 queueDemo[1870:101850] [NSThread sleepForTimeInterval:1]; 2015-05-21 14:32:15.901 queueDemo[1870:101851] [NSThread sleepForTimeInterval:3]; */
总计:dispatch_barrier_async的顺序执行是依赖queue的类型,必需要queue的类型为dispatch_queue_create创建的,而且attr参数值必需是DISPATCH_QUEUE_CONCURRENT类型
四.dispatch_once
dispatch_once这个函数,它可以保证整个应用程序生命周期中某段代码只被执行一次!多用于对单例的操作。
-
static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // code to be executed once });
五.Dispatch Queue的延迟执行:dispatch_after():
延时操作大都用这个[self performSelector:@selector(btn) withObject:nil afterDelay:1];或者定时
但这两个个方法执行效率低,而且定时时间不准时。所以现在一般都用GCD这个。
-
double delayInSeconds = 2.0; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); // * NSEC_PER_SEC 这个不能省,否则就是2毫秒了,默认是毫秒,NSEC_PER_SEC表示秒 NSEC_PER_MSEC表示毫秒 dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ // code to be executed on the main queue after delay });
六.线程队列的挂起与执行
// 挂起队列 dispatch_suspend(queue); // 恢复队列执行 dispatch_resume(queue);
七.其他
dispatch_apply 执行某个代码片段N次。
dispatch_set_target_queue 可以设置一个dispatch queue的优先级,或者指定一个dispatch source相应的事件处理提交到哪个queue上。
附代码:http://i.cnblogs.com/Files.aspx queueDemo.zip
推荐文章:http://my.oschina.net/aofe/blog/270093
http://blog.csdn.net/samuelltk/article/details/9452203
http://www.cnblogs.com/SnailFish/articles/3199863.html
http://www.cocoachina.com/industry/20131210/7506_2.html