今天周末,聊一聊GCD。想从三个方面说说GCD,分别是什么是GCD,GCD的API,GCD是怎么实现的。
什么是GCD
NSThread,GCD ,NSOperation的比较
- 苹果的多线程编程,我们常见的经常使用的有NSThread,GCD,NSOperation。
NSThread 是对每一个线程对象进行的封装,优点是可以控制线程对象的生命周期,包括创建,开始,挂起,暂停,销毁等操作。缺点也很明显,线程的每个状态都需要自己管理。其实开启多线程,目的是为了在线程里面去执行任务,使用NSThread开发人员不仅要关注任务,还要关注NSThread本身的操作。 - GCD 是一个异步执行任务的技术。应用中线程管理的代码在系统级中实现。开发者所需要做的只是定义任务,然后把任务放到Dispatch Queue中,GCD就能够生成必要的线程并计划执行任务。
优点:线程管理是作为系统的一部分来实现的,可以统一管理,所以执行效率相比以前的线程执行效率更高。
GCD的API
Dispatch Queue
GCD的定义就是将异步的任务,追加到适当的Dispatch Queue中。
dispatch_async (queue,^{
/*
* 想执行的任务
*/
})
- Dispatch Queue 是执行任务的等待队列。因为是队列,遵循先进先出原则。 也就是说按照追加的顺序执行。
- Dispatch Queue 有两种队列,串行队列和并行队列。串行队列,等待当前执行任务结束。并行队列,不需要等待当前任务执行结束。
注意GCD中的队列的任务的执行顺序都是按追加的前后顺序 -
串行队列 因为等待当前任务完成在执行下一个任务,所以用到的只是一个线程。
并行队列 因为无需等待当前任务完成,就可执行下一个任务,所以用到多个线程。
Dispatch Queue Create
- Dispatch Queue 创建有两种方式,第一种是通过GCD 提供的API dispatch_queue_ create创建,另一种是获取系统提供的的Dispatch Queue。系统提供两种Dispatch Queue,一种是Main Dispatch Queue,另一种是Global Dispatch Queue。
- Global Dispatch Queue 有四种优先级 一般情况都是用默认优先级,很少用到其他的优先级。
dispatch_set_target_queue
dispatch_after
dispatch_after延迟执行
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,3ull * NESC_PER_SEC);
dispatch_after(time,dispatch_get_main_queue(),^{
NSLog(@"waited at least three seconds.");
});
需要注意的地方: dispatch_after 函数并不是在指定时间后执行处理,而是在指定的时间追加处理到Dispatch Queue.
Dispatch Group
当Dispatch Queue中的任务都执行完毕的时候,需要执行一个结束处理,这种情况经常出现。
dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORY_DEFAULT,0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group,queue,^{NSLog(@"blk0");});
dispatch_group_async(group,queue,^{NSLog(@"blk1");});
dispatch_group_async(group,queue,^{NSLog(@"blk2");});
dispatch_group_notify(group,dispatch_get_main_queue(),^{NSLog(@"done");});
dispatch_release(group);
另外,在Dispatch Group中也可以使用dispatch_group_wait 函数,这个也是等待队列中全部处理都结束了,然后在执行。
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,^{(NSlog(@"blk0");});
dispatch_group_async(group,queue,^{(NSlog(@"blk1");});
dispatch_group_async(group,queue,^{(NSlog(@"blk3");});
dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
dispatch_release(group);
dispatch_group_wait第二个参数指定为等待的时间(超时时间),该代码中的DISPATCH_TIME_FOREVER,意味着永久等待。只要属于Dispatch Group的处理尚未执行结束,就会一直等待,中途不能取消。
dispatch_barrier_async
访问数据库或文件时,使用串行队列,可以避免数据竞争的问题。
写入处理,确实不可以与其他的写入处理以及包含读取处理的其他某些处理并行执行,但是如果读取处理知识与读取处理并行执行,这些并行执行就不会出现问题。
为了高效的进行访问,读取处理追加到并行队列中,写入处理追加到串行队列中。
dispatch_sync
dispatch_async函数的“async”意味着非同步,指定的block,以非同步的方式追加到指定的dispatch_queue中。
dispatch_sync函数的"sync"意味着同步,指定的block,以同步的方式,追加到指定的dispatch_queue中。在追加的block结束之前,dispatch_sync函数会一直等待。
dispatch_apply
dispatch_apply 函数是dispatch_async函数和Dispatch Group的关联API。这个函数有点像for循环,按指定的次数,将指定的Block追加到指定的Dispatch Queue 中,并等待全部处理执行结束。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_apply(10,queue,^(size_t index){
NSlog(@"%zu",index);
});
NSLog(@"done");
dispatch_suspend / dispatch_resume
在追加处理的过程中,有时候不希望执行已追加的处理。在这种情况下,只要挂起Dispatch Queue即可。当可以执行时,在恢复。
dispatch_suspend函数挂起指定的Dispatch Queue.
dispatch_suspend(queue);
dispatch_resume 函数恢复指定的Dispatch Queue.
dispatch_resume(queue);
dispatch_once
dispatch_onec保证在程序中只执行一次的指定处理API.
网友评论