iOS多线程编程之GCD
来源:互联网 发布:sql语句高级查询 编辑:程序博客网 时间:2024/05/18 18:16
1.GCD介绍
Grand Central Dispatch 简称(GCD)是Apple公司开发的技术,相比NSThread或NSOperation使用方便,并且优点是当处理器为多核时能利用多核的特征来创建线程。它首次发布在Mac OS X 10.6 ,iOS 4及以上也可用。
2.GCD分类
GCD中的FIFO队列称为dispatch queue,它可以保证先进来的任务先得到执行,dispatch queue分为下面3种:一种是串行队列(Serial Dispatch Queue),一种是并行队列(Concurrent Dispatch Queue),还有一个是主队列(Main dispatch queue).
2.1 串行队列(Serial Dispatch Queue)
又称为private dispatch queues,同时只执行一个任务。Serial queue通常用于同步访问特定的资源或数据。当你创建多个Serial queue时,虽然它们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。
- (void)serialQueue {dispatch_queue_t serialQueue = dispatch_queue_create("http://blog.csdn.net/zhangwenhai001", DISPATCH_QUEUE_SERIAL);dispatch_async(serialQueue, ^{NSLog(@"serialQueue1 -- %@",[NSThread currentThread]);});dispatch_async(serialQueue, ^{NSLog(@"serialQueue2 -- %@",[NSThread currentThread]);});}运行结果为:
2015-07-06 21:01:44.583 GCD复习[1113:175900] serialQueue1 -- <NSThread: 0x7fccb8e159f0>{number = 2, name = (null)}2015-07-06 21:01:44.584 GCD复习[1113:175900] serialQueue2 -- <NSThread: 0x7fccb8e159f0>{number = 2, name = (null)}结论:在serial queue中按顺序执行任务,主线程以外会开一个线程,看运行结果时间.
2.2 并行队列(Concurrent Dispatch Queue)
又称为global dispatch queue,可以并发地执行多个任务,但是执行完成的顺序是随机的。
- (void)concurrentQueue {dispatch_queue_t concurrentQueue = dispatch_queue_create("http://blog.csdn.net/zhangwenhai001", DISPATCH_QUEUE_CONCURRENT);dispatch_async(concurrentQueue, ^{NSLog(@"concurrentQueue1 -- %@",[NSThread currentThread]);});dispatch_async(concurrentQueue, ^{NSLog(@"concurrentQueue2 -- %@",[NSThread currentThread]);});}运行结果为:
2015-07-06 21:06:02.264 GCD复习[1218:178568] concurrentQueue1 -- <NSThread: 0x7f9c6b715520>{number = 2, name = (null)}2015-07-06 21:06:02.264 GCD复习[1218:178567] concurrentQueue2 -- <NSThread: 0x7f9c6b5103a0>{number = 3, name = (null)}2015-07-06 21:06:02.264 GCD复习[1218:178569] concurrentQueue3 -- <NSThread: 0x7f9c6b649c40>{number = 4, name = (null)}结论:在concurrent queue中,任务是并发执行,并每个任务开一个子线程,看运行结果时间.
2.3 主队列(Main dispatch queue)
它是全局可用的serial queue,它是在应用程序主线程上执行任务的,在程序的RunLoop中执行。
- (void)mainQueue {dispatch_queue_t mainQueue = dispatch_get_main_queue();dispatch_async(mainQueue, ^{NSLog(@"mainQueue1 -- %@",[NSThread currentThread]);});dispatch_async(mainQueue, ^{NSLog(@"mainQueue2 -- %@",[NSThread currentThread]);});dispatch_async(mainQueue, ^{NSLog(@"mainQueue3 -- %@",[NSThread currentThread]);});}运行结果为:
2015-07-06 21:10:03.982 GCD复习[1239:180152] mainQueue1 -- <NSThread: 0x7ffad0628050>{number = 1, name = main}2015-07-06 21:10:03.983 GCD复习[1239:180152] mainQueue2 -- <NSThread: 0x7ffad0628050>{number = 1, name = main}2015-07-06 21:10:03.983 GCD复习[1239:180152] mainQueue3 -- <NSThread: 0x7ffad0628050>{number = 1, name = main}结论:所有任务会在主线程中阻塞性执行,按顺序一个一个执行,并不会创建新的线程.
3. 系统的Dispatch Queue
3.1 Main Dispatch Queue
主线程队列(Serial Queue), 在程序的RunLoop中执行。
获取方法:
dispatch_queue_t mainQueue = dispatch_get_main_queue();
3.2 Global Dispatch Queue
Global Dispatch Queue: 系统中所有应用程序共用的全局队列(Concurrent Queue), 一般不必创建新的Dispatch Queue,使用此Queue就可以了。
Global Diapacth Queue有4个优先级:High Priority(高)、Default Priority(默认)、Low Priority(低)、Background Priority(后台)。
dispatch_queue_t globalDispatchQueueDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3.3 举例解释
举例下载图片并刷新UI,main dispatch Queue和global dispatch Queue的结合使用:
- (void)globalQueue {dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{//downLoadImagedispatch_async(dispatch_get_main_queue(), ^{//refresh UI});});}
4.dispatch_group_async的使用
dispatch_group_async可以实现监听一组任务是否完成,完成后得到通知执行其他的操作。这个方法很有用,比如你执行三个下载任务,当三个任务都下载完成后你才通知界面说完成的了。
实例代码如下:
- (void)dispatchGroupAsync {dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_group_t dispatchGroup = dispatch_group_create();dispatch_group_async(dispatchGroup, globalQueue, ^{NSLog(@"task1--%@",[NSThread currentThread]);});dispatch_group_async(dispatchGroup, globalQueue, ^{[NSThread sleepForTimeInterval:2.0];NSLog(@"task2--%@",[NSThread currentThread]);});dispatch_group_async(dispatchGroup, globalQueue, ^{[NSThread sleepForTimeInterval:1.0];NSLog(@"task3--%@",[NSThread currentThread]);});dispatch_group_notify(dispatchGroup, globalQueue, ^{NSLog(@"dispatch_group_notify queue finished!");});}运行结果为:
2015-07-06 21:34:08.362 GCD复习[1347:189003] task1--<NSThread: 0x7fdbcb429e70>{number = 2, name = (null)}2015-07-06 21:34:09.367 GCD复习[1347:189009] task3--<NSThread: 0x7fdbcb61c910>{number = 3, name = (null)}2015-07-06 21:34:10.367 GCD复习[1347:189005] task2--<NSThread: 0x7fdbcb615660>{number = 4, name = (null)}2015-07-06 21:34:10.367 GCD复习[1347:189005] dispatch_group_notify queue finished!结论:
在并行的多个子线程任务结束后能得到通知.
5.dispatch_barrier_async的使用
dispatch_barrier_async是在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行,相当于我说执行在哪里就是那里.
但是在concurrentQueue中.
<span style="font-size:14px;">- (void)dispatchBarrierAsync {dispatch_queue_t concurrentQueue = dispatch_queue_create("http://blog.csdn.net/zhangwenhai001", DISPATCH_QUEUE_CONCURRENT);dispatch_async(concurrentQueue, ^{NSLog(@"dispatch_async1 -- %@",[NSThread currentThread]);});dispatch_barrier_async(concurrentQueue, ^{NSLog(@"dispatch_barrier_async -- %@",[NSThread currentThread]);});dispatch_async(concurrentQueue, ^{NSLog(@"dispatch_async2 -- %@",[NSThread currentThread]);});}</span>
运行结果:
2015-07-06 21:44:41.202 GCD复习[1414:192934] dispatch_async1 -- <NSThread: 0x7fb511503fe0>{number = 2, name = (null)}2015-07-06 21:44:41.203 GCD复习[1414:192934] dispatch_barrier_async -- <NSThread: 0x7fb511503fe0>{number = 2, name = (null)}2015-07-06 21:44:41.203 GCD复习[1414:192934] dispatch_async2 -- <NSThread: 0x7fb511503fe0>{number = 2, name = (null)}6.dispatch_apply
执行block中代码N次.
- (void)dispatchApply {dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_apply(3, globalQueue, ^(size_t index) {NSLog(@"I`m dispatchApply%zu -- %@",index,[NSThread currentThread]);});}
运行结果为:
2015-07-06 21:51:33.455 GCD复习[1508:196299] I`m dispatchApply0 -- <NSThread: 0x7f9848516f10>{number = 1, name = main}2015-07-06 21:51:33.455 GCD复习[1508:196322] I`m dispatchApply2 -- <NSThread: 0x7f9848674f50>{number = 3, name = (null)}2015-07-06 21:51:33.455 GCD复习[1508:196323] I`m dispatchApply1 -- <NSThread: 0x7f9848408940>{number = 2, name = (null)}结论:
从运行结果得知,dispatch_apply的dispatch_queue_t不能为dispatch_main_queue,因为"I`m dispatchApply0"占用的是主线程.
7.dispatch_once
block内部的代码在app声明周期内只执行一次.
- (void)dispatchOnce {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{NSLog(@"I`m dispatch_once_t-- %@",[NSThread currentThread]);});}运行结果为:
2015-07-06 21:57:33.937 GCD复习[1529:198306] I`m dispatch_once_t-- <NSThread: 0x7f8658518540>{number = 1, name = main}
8.queue的暂停和恢复
使用dispatch_suspend(queue)可以暂停队列中任务的执行,使用dispatch_result(queue)可以继续执行被暂停的队列。
参考:http://blog.csdn.net/totogo2010/article/details/8016129
---end
- iOS多线程编程之GCD
- iOS多线程编程之GCD
- iOS 多线程编程之GCD
- iOS多线程编程之GCD
- iOS-多线程编程之GCD
- iOS多线程编程之GCD介绍
- iOS多线程编程之GCD的使用
- iOS多线程编程--GCD
- iOS多线程编程GCD
- iOS 多线程之----------GCD
- IOS多线程之GCD
- IOS 多线程之GCD
- iOS多线程之GCD
- ios多线程之GCD
- iOS多线程之GCD
- ios多线程之GCD
- IOS多线程之GCD
- IOS多线程之GCD
- iOS 关于objc_setAssociatedObject,objc_getAssociatedObject
- Application对象
- Java RMI例子
- 二叉树 二叉树的性质 存储结构 遍历二叉树 C实现二叉树的创建和遍历 线索二叉树
- Java IO之Reader/Writer
- iOS多线程编程之GCD
- linearlayout 居中问题
- 基于mongodb, 设计游戏中的个人背包系统
- C++程序常见的性能调优方式
- Android模拟器Genymotion学习笔记
- Reverse digits of an integer.
- 51nod round3# 序列分解(折半枚举+字典树)
- [Phonegap+Sencha Touch] 移动开发53 Cordova/Phonegap 4(或5) 多了什么?
- hdu 1867 A + B for you again