多线程 - 07.GCD函数和队列组合示例
来源:互联网 发布:js中get post 区别 编辑:程序博客网 时间:2024/06/06 11:41
1.GCD基本使用(异步函数+并发队列)
- 可以看到,系统自动给开辟了新的子线程来执行这三个任务,且由于时并发队列,系统开辟了三个子线程
- 注意:开辟多少个子线程由系统决定,三个任务依次从队列中取出放在不同的子线程执行,但是由于CPU调度子线程是由系统控制的,所以任务执行的顺序不定,并没有违背队列中任务的先进先出原则
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ // 1.创建队列 /* 参数解释 第一个参数:队列名称 第二个参数:队列属性(串行还是并发) DISPATCH_QUEUE_SERIAL :串行 DISPATCH_QUEUE_CONCURRENT 并发 */ // 1.1创建一个并发队列// dispatch_queue_t queue = dispatch_queue_create("zj.queue", DISPATCH_QUEUE_CONCURRENT); // 1.2系统内部已经给我们提供好了一个现成的并发队列 /* 第一个参数: iOS8以前是优先级, iOS8以后是服务质量 iOS8以前 * - DISPATCH_QUEUE_PRIORITY_HIGH 高优先级 2 * - DISPATCH_QUEUE_PRIORITY_DEFAULT: 默认的优先级 0 * - DISPATCH_QUEUE_PRIORITY_LOW: 低优先级 -2 * - DISPATCH_QUEUE_PRIORITY_BACKGROUND: 后台 iOS8以后 * - QOS_CLASS_USER_INTERACTIVE 0x21 用户交互(用户迫切想执行任务) * - QOS_CLASS_USER_INITIATED 0x19 用户需要 * - QOS_CLASS_DEFAULT 0x15 默认 * - QOS_CLASS_UTILITY 0x11 工具(低优先级, 苹果推荐将耗时操作放到这种类型的队列中) * - QOS_CLASS_BACKGROUND 0x09 后台 * - QOS_CLASS_UNSPECIFIED 0x00 没有设置 第二个参数: Flags that are reserved for future use. Always specify 0 for this parameter. 根据苹果文档,可以知道这是一个保留值,以便苹果在系统内部执行一些操作,并且苹果建议我们始终传入0即可. */ // 为了同时适配iOS8以及iOS8以前的版本,优先级参数直接传0即可 dispatch_queue_t queue = dispatch_get_global_queue(0, 0); // 2.添加任务到队列(这里使用异步方式) /* 参数解释 第一个参数:需要将任务添加到哪个队列 第二个参数:需要执行的任务 */ // 连续添加三个任务 dispatch_async(queue, ^{ NSLog(@"%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"%@",[NSThread currentThread]); }); /* 结果:(每次打印的线程number顺序不一致) <NSThread: 0x7fb878d02110>{number = 4, name = (null)} <NSThread: 0x7fb878e21500>{number = 3, name = (null)} <NSThread: 0x7fb878f91e20>{number = 2, name = (null)} */}
2.GCD基本使用(异步函数+串行队列)
- 可以看到,开启了新的线程,但是只开启了一条
- 能够创建新线程的原因:使用”异步”函数调用
- 只创建1个子线程的原因:队列是串行队列
- 由于队列串行队列,所以任务是从上到下依次执行
- 由于使用了异步函数,那么不会等到异步函数中的任务执行完毕再去执行后面的代码
- (void)asynSerial{ // 1.创建串行队列 dispatch_queue_t queue = dispatch_queue_create("zj.queue", DISPATCH_QUEUE_SERIAL); // 2.添加任务到队列 // 连续添加三个任务 dispatch_async(queue, ^{ NSLog(@"任务一执行,%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"任务二执行,%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"任务三执行,%@",[NSThread currentThread]); }); NSLog(@"+++++++"); /* 打印结果: 任务一执行,<NSThread: 0x7fdb91720450>{number = 2, name = (null)} +++++++ 任务二执行,<NSThread: 0x7fdb91720450>{number = 2, name = (null)} 任务三执行,<NSThread: 0x7fdb91720450>{number = 2, name = (null)} */}
3.GCD基本使用(同步函数+串行队列)
- 可以看到不会开启新的线程,且线程中的任务会依次执行
- 因为调用了同步函数, 那么会等同步函数中的任务执行完毕, 才会执行后面的代码
- (void)syncSerial{ // 1.创建一个串行队列 // #define DISPATCH_QUEUE_SERIAL NULL // 所以可以直接传NULL dispatch_queue_t queue = dispatch_queue_create("zj.queue", NULL); // 2.将任务添加到队列中 dispatch_sync(queue, ^{ NSLog(@"任务1 == %@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"任务2 == %@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"任务3 == %@", [NSThread currentThread]); }); NSLog(@"---------"); /*输出结果: 任务1 == <NSThread: 0x7fe129512690>{number = 1, name = main} 任务2 == <NSThread: 0x7fe129512690>{number = 1, name = main} 任务3 == <NSThread: 0x7fe129512690>{number = 1, name = main} --------- */}
4.GCD基本使用(同步函数+并发队列)
- 使用了同步函数,不会创建新的线程
/* 同步 + 并发 : 不会开启新的线程 */- (void)syncConCurrent{ // 1.创建一个并发队列 dispatch_queue_t queue = dispatch_get_global_queue(0, 0); // 2.将任务添加到队列中 dispatch_sync(queue, ^{ NSLog(@"任务1 == %@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"任务2 == %@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"任务3 == %@", [NSThread currentThread]); }); NSLog(@"---------"); /*输出结果: 任务1 == <NSThread: 0x7fe129512690>{number = 1, name = main} 任务2 == <NSThread: 0x7fe129512690>{number = 1, name = main} 任务3 == <NSThread: 0x7fe129512690>{number = 1, name = main} --------- */}
5.GCD基本使用(异步函数+主队列)
- 只要是在主队列,那么无论是调用同步还是异步函数,都不会开启新线程,一定会在主线程中执行
/* 异步 + 主队列 : 不会创建新的线程,并且任务是在主线程中执行 */- (void)asyncMain{ // 创建主队列 dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue, ^{ NSLog(@"%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"%@", [NSThread currentThread]); });} /* 输出结果: 任务一 <NSThread: 0x7fa1d35267c0>{number = 1, name = main} 任务二 <NSThread: 0x7fa1d35267c0>{number = 1, name = main} */
6.GCD基本使用(同步函数+主队列)-死锁
- 如果是在主线程中调用同步函数 + 主队列, 那么会导致死锁
导致死锁的原因:- sync函数是在主线程中执行的, 并且会等待block执行完毕. 先调用
- block是添加到主队列的, 也需要在主线程中执行. 后调用
- 由于队列的先进先出原则,那么sync函数要先执行,但是他又要等待block执行完毕才会往后继续执行,block又在主队列的后面,等待同步函数执行完毕后才会执行,所以两个任务相互等待,永远都不会往下继续执行,造成死锁
/* 在主线程中调用同步函数+主队列会导致死锁 */- (void)syncMain{ NSLog(@"%@", [NSThread currentThread]); // 主队列: dispatch_queue_t queue = dispatch_get_main_queue(); // 如果是调用 同步函数, 那么会等同步函数中的任务执行完毕, 才会执行后面的代码 // 注意: 如果dispatch_sync方法是在主线程中调用的, 并且传入的队列是主队列, 那么会导致死锁 dispatch_sync(queue, ^{ NSLog(@"----------"); NSLog(@"%@", [NSThread currentThread]); }); NSLog(@"----------");}/* 输出结果:队列中的任务以及主线程中后续的操作不再执行<NSThread: 0x7fadbad1ba70>{number = 1, name = main}*/
7.GCD基本使用(同步函数+主队列)-不死锁
- 要想使用同步函数和主队列,且不造成死锁,可以在子线程中执行同步函数
/* 如果是在子线程中调用 同步函数 + 主队列, 那么没有任何问题 */- (void)syncMain2{ dispatch_queue_t queue = dispatch_get_global_queue(0, 0); dispatch_async(queue, ^{ // block会在子线程中执行 // NSLog(@"%@", [NSThread currentThread]); dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_sync(queue, ^{ // block一定会在主线程执行 NSLog(@"%@", [NSThread currentThread]); }); }); NSLog(@"------------"); /* 输出结果: ------------ <NSThread: 0x7fd16af280d0>{number = 1, name = main} */}
0 0
- 多线程 - 07.GCD函数和队列组合示例
- GCD的四种队列,两种函数和六种组合
- [网络和多线程]6、GCD 队列和任务
- iOS 开发 多线程详解之GCD任务和队列
- 4.iOS多线程中,GCD技术的队列与执行方式的组合结果
- iOS - GCD(多线程)简单示例:
- 网络多线程-GCD队列组
- 使用GCD实现多线程队列
- iOS--多线程GCD队列--06
- 多线程GCD的详细讲解 任务和队列(串行队列,并发队列) (一)
- 多线程GCD的详细讲解 任务和队列(串行队列,并发队列)
- GCD中的队列与任务组合对比
- GCD关于队列和函数对于调用线程的影响
- iOS-多线程编程学习之GCD——串行队列和并发队列(五)
- iOS中多线程知识总结:进程、线程、GCD、串行队列、并行队列、全局队列、主线程队列、同步任务、异步任务等(有示例代码)
- GCD和多线程
- 多线程 GCD和NSOperation
- GCD之同步函数、异步函数和串行队列、并发队列
- linux下50个常用命令
- [c] sdnuoj1147Pythagoras's Revenge
- hdoj-2066 一个人的旅行【最短路径--dijkstra&&spfa&&floyd】
- C# LinkedList<T> 泛型类的实现
- FZU 2135 数字游戏
- 多线程 - 07.GCD函数和队列组合示例
- The hardest problem
- 【C++】复数类
- 软件架构的道德责任
- 动画
- 常用传感器协议6:中立格林VOC传感器
- BUG与异常小结
- uva 10652 - Board Wrapping(凸包)
- ssh常见错误