Grand Central Dispatch(GCD)包含语言特点、运行库和系统增强功能,它提供系统的、综合的改进,进而去支持并发代码在iOS和OSX多核硬件上的执行。
子系统、CoreFoundation和Cocoa APIs 已经都延伸去使用这些功能,进而帮助系统和你的应用程序运行地更快,更高效,而且提高响应能力。考虑到一个程序有效使用多核的困难性,更不要说在不同的计算机中使用不同数量的计算机内核或者多个应用程序环境中竞争核。CGC,一个在系统层面的操作,可以更好的适应所有运行程序的需要,以平衡的方式去匹配可用系统资源。
这个文档用来描述GCD 的API,它在Unix系统水平支持异步执行操作。你可以使用这些API来管理与文件描述符、Mach 端口、信号或者计时器的相互作用。在OS Xv10.7以及以后,你也可以使用GCD去处理常规目的的异步I/O操作。
GCD并不限制于系统级别的应用程序,但是在你使用它到更高级别的应用程序中之前,你应该考虑一下Cocoa提供的简单的函数是不是比GCD更简单去满足你程序的需求。
当你在把CGD和fork系统调用混合适用的时候,如果一个进程GCD调用优先于fork调用,这样就是不安全的。指导成功调用exec或者相关函数之后才安全。
void dispatch_async ( dispatch_queue_t queue, dispatch_block_t block );
void dispatch_sync ( dispatch_queue_t queue, dispatch_block_t block );
串行队列:任务一个接着一个执行。
dispatch_get_global_queue
函数获得全局的并发队列。创建串行队列
串行队列可以通过以下两种方式获得:
dispatch_queue_create
创建dispatch_get_main_queue()
,朱队列是GCD自带的一种特殊的串行队列,放在主队列的任务都会在主线程中执行。当你使用OC编译器运行你的app时,所有的dispatch对象都是OC对象。同样的,当自动引用计数(ARC)允许时,dispatch对象的保持和释放都是自动的,就像其他OC对象一样。当ARC不允许时,使用dispatch_retain
和dispatch_release
函数(或者OC语言)去保持和释放你的dispatch对象。你不能使用Core Foundation retain/release
函数去保持和释放dispatch对象。
在晚一些的的项目构建中,如果你需要在ARC允许的app中使用retain/release
语法(为了维护与现有代码的兼容性),你可以禁用OC dispathc对象通过添加 -DOS_OBJECT_USE_OBJE=0到你的编译器标示中。
dispatch_ get_main_queue
dispatch_queue_t dispatch_get_main_queue ( void );
主线程上调用异步
- (void)syncOnMainThread{ NSLog(@"task2:%@",[NSThread currentThread]); dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue, ^{ NSLog(@"task1:%@",[NSThread currentThread]); }); NSLog(@"task3:%@",[NSThread currentThread]);}
输出结果:
死锁:使用同步函数在主队列执行,会造成线程死锁情况
- (void)testDeadLock{ NSLog(@"task2:%@",[NSThread currentThread]); dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_sync(queue, ^{ NSLog(@"task1:%@",[NSThread currentThread]); }); NSLog(@"task3:%@",[NSThread currentThread]);}
同步执行串行队列:不会开启新线程,按照顺序执行
- (void)syncChuanxing{ dispatch_queue_t queue = dispatch_queue_create("gcd.queue", NULL); //添加任务到队列中执行任务 dispatch_sync(queue, ^{ NSLog(@"task1:%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"task2:%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"task3:%@",[NSThread currentThread]); });}
执行结果:
在同步函数中执行并发任务:在主线程中按顺序执行,并发队列失去并发功能
- (void)syncBingfa{ dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //添加任务到队列中执行任务 dispatch_sync(queue, ^{ NSLog(@"task1:%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"task2:%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"task3:%@",[NSThread currentThread]); }); }
执行结果:
异步函数在串行队列上执行:可见程序开启单个线程的顺序执行
- (void)asynChuanxing{ //获得全局的并发队列 dispatch_queue_t queue =dispatch_queue_create("gcd.queue", NULL);// dispatch_queue_t queue =dispatch_get_main_queue(); //添加任务到队列中执行任务 dispatch_async(queue, ^{ NSLog(@"task1:%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"task2:%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"task3:%@",[NSThread currentThread]); });}
执行结果:
异步函数在并行队列上执行
- (void)asynBingxing{ //获得全局的并发队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //添加任务到队列中执行任务 dispatch_async(queue, ^{ NSLog(@"task1:%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"task2:%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"task3:%@",[NSThread currentThread]); });}
执行结果:
每次执行的结果可能不一样
延时执行
- (void)deleayRun{ //通常的延时执行 dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue, ^{ [self performSelector:@selector(runWith:) withObject:@"2" afterDelay:2.0]; }); //gcd函数执行 dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0*NSEC_PER_SEC)); dispatch_after(when, queue1, ^{ [self runWith:1]; }); //上边的gcd函数执行和这个一样 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self runWith:2]; }); }#pragma mark - RunMethod- (void)runWith:(NSInteger)tag{ NSLog(@"执行函数:%ld",(long)tag);}
组队列
- (void)zuDuiLie{ // 创建一个组 dispatch_group_t group = dispatch_group_create(); // 下载图片1 dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"下载图片1:%@",[NSThread currentThread]); }); // 下载图片2 dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"下载图片2:%@",[NSThread currentThread]); }); // group任务都执行完毕,再执行其他操作 dispatch_group_notify(group, dispatch_get_main_queue(), ^{ // 合并图片 NSLog(@"开始合并图片:%@",[NSThread currentThread]); });}
执行结果:
1、 线程:1个CPU执行的CPU命令列为一条无分叉的路径即为一个线程。
2、dispatch_queue_create的作用是创建一个派遣队列,是串行队列。
3、dispatch_set_target_queue:变更生成的Dispatch_Queue的执行优先级要使用dispatch_set_target_queue函数。它有两个参数,第一个参数是指定要变更执行优先级的Dispatch Queue;第二个参数是指定要使用的执行优先级相同优先级的Global Dispatch Queue为第二个参数。
4、dispatch_after:延迟执行
5、dispatch_group_notify:是把多个处理全部结束后再执行结束处理。最后可以用dispatch_group_notify(group名称)执行结束处理。
6、dispatch_group_wait:等待全部处理执行结束。
7、dispatch_barrier_async:会等待追加到并发派遣队列上的并行执行的处理全部结束之后,再将制定的函数处理追加到并发派遣队列。(有点类似于addDepency)先处理前面的几个操作,然后遇到barrier后只执行1个barrier追加的处理,然后再继续执行后面的处理。
8、dispatch_apply:该函数按照指定的次序将指定的Block追加到指定的Dispatch Queue中,并等待全部处理执行结束。
9、dispatch_suspend/dispatch_resume:用于有时候不希望执行以追加的处理。
10、dispatch_once:保证在应用程序执行中只执行一次指定处理。
新闻热点
疑难解答