串行队列

特点

  • 以先进先出的方式,顺序调度队列中的任务执行
  • 无论队列中所指定的执行任务函数是同步还是异步,都会等待前一个任务执行完成后,再调度后面的任务

队列创建

dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_SERIAL);

dispatch_queue_t queue = dispatch_queue_create("queueName", NULL);

串行队列演练

1 串行队列 同步执行

/**

提问:是否开线程?是否顺序执行?come here 的位置?

*/

- (void)gcdDemo1 {

// 1. 队列

dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_SERIAL);

// 2. 执行任务

for (int i = 0; i < 10; ++i) {

NSLog(@"--- %d", i);

dispatch_sync(q, ^{

NSLog(@"%@ - %d", [NSThread currentThread], i);

});

}

NSLog(@"come here");

}

  • 串行队列 异步执行

/**

提问:是否开线程?是否顺序执行?come here 的位置?

*/

- (void)gcdDemo2 {

// 1. 队列

dispatch_queue_t q = dispatch_queue_create("foo", NULL);

// 2. 执行任务

for (int i = 0; i < 10; ++i) {

NSLog(@"--- %@ %d", [NSThread currentThread], i);

dispatch_async(q, ^{

NSLog(@"%@ - %d", [NSThread currentThread], i);

});

}

NSLog(@"come here");

}

并发队列

特点

  • 以先进先出的方式,并发调度队列中的任务执行
  • 如果当前调度的任务是同步执行的,会等待任务执行完成后,再调度后续的任务
  • 如果当前调度的任务是异步执行的,同时底层线程池有可用的线程资源,会再新的线程调度后续任务的执行

队列创建

dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_CONCURRENT);

并发队列演练

  • 并发队列 异步执行

/**

提问:是否开线程?是否顺序执行?come here 的位置?

*/

- (void)gcdDemo3 {

// 1. 队列

dispatch_queue_t q = dispatch_queue_create("foo", DISPATCH_QUEUE_CONCURRENT);

// 2. 执行任务

for (int i = 0; i < 10; ++i) {

dispatch_async(q, ^{

NSLog(@"%@ - %d", [NSThread currentThread], i);

});

}

NSLog(@"come here");

}

  • 并发队列 同步执行

/**

提问:是否开线程?是否顺序执行?come here 的位置?

*/

- (void)gcdDemo4 {

// 1. 队列

dispatch_queue_t q = dispatch_queue_create("foo", DISPATCH_QUEUE_CONCURRENT);

// 2. 执行任务

for (int i = 0; i < 10; ++i) {

dispatch_sync(q, ^{

NSLog(@"%@ - %d", [NSThread currentThread], i);

});

NSLog(@"---> %i", i);

}

NSLog(@"come here");

}

主队列

特点

  • 专门用来在主线程上调度任务的队列
  • 不会开启线程
  • 以先进先出的方式,在主线程空闲时才会调度队列中的任务在主线程执行
  • 如果当前主线程正在有任务执行,那么无论主队列中当前被添加了什么任务,都不会被调度

队列获取

  • 主队列是负责在主线程调度任务的
  • 会随着程序启动一起创建
  • 主队列只需要获取不用创建

dispatch_queue_t queue = dispatch_get_main_queue();

主队列演练

  • 主队列,异步执行

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

[self gcdDemo1];

[NSThread sleepForTimeInterval:1];

NSLog(@"over");

}

- (void)gcdDemo1 {

dispatch_queue_t queue = dispatch_get_main_queue();

for (int i = 0; i < 10; ++i) {

dispatch_async(queue, ^{

NSLog(@"%@ - %d", [NSThread currentThread], i);

});

NSLog(@"---> %d", i);

}

NSLog(@"come here");

}

在主线程空闲时才会调度队列中的任务在主线程执行

  • 主队列,同步执行

// MARK: 主队列,同步任务

- (void)gcdDemo6 {

// 1. 队列

dispatch_queue_t q = dispatch_get_main_queue();

NSLog(@"!!!");

// 2. 同步

dispatch_sync(q, ^{

NSLog(@"%@", [NSThread currentThread]);

});

NSLog(@"come here");

}

主队列和主线程相互等待会造成死锁

同步任务的作用

同步任务,可以让其他异步执行的任务,依赖某一个同步任务

例如:在用户登录之后,再异步下载文件!

- (void)gcdDemo1 {

dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_CONCURRENT);

dispatch_sync(queue, ^{

NSLog(@"登录 %@", [NSThread currentThread]);

});

dispatch_async(queue, ^{

NSLog(@"下载 A %@", [NSThread currentThread]);

});

dispatch_async(queue, ^{

NSLog(@"下载 B %@", [NSThread currentThread]);

});

}

  • 代码改造,让登录也在异步执行

- (void)gcdDemo2 {

dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_CONCURRENT);

void (^task)() = ^{

dispatch_sync(queue, ^{

NSLog(@"登录 %@", [NSThread currentThread]);

});

dispatch_async(queue, ^{

NSLog(@"下载 A %@", [NSThread currentThread]);

});

dispatch_async(queue, ^{

NSLog(@"下载 B %@", [NSThread currentThread]);

});

};

dispatch_async(queue, task);

}

1  主队列调度同步队列不死锁

- (void)gcdDemo3 {

dispatch_queue_t queue = dispatch_queue_create("queueName", DISPATCH_QUEUE_CONCURRENT);

void (^task)() = ^ {

dispatch_sync(dispatch_get_main_queue(), ^{

NSLog(@"死?");

});

};

dispatch_async(queue, task);

}

主队列在主线程空闲时才会调度队列中的任务在主线程执行

全局队列

  • 是系统为了方便程序员开发提供的,其工作表现与并发队列一致

全局队列 & 并发队列的区别

1  全局队列

◦                     没有名称

◦                     无论 MRC & ARC 都不需要考虑释放

◦                     日常开发中,建议使用"全局队列"

2  并发队列

◦                     有名字,和 NSThread 的 name 属性作用类似

◦                     如果在 MRC 开发时,需要使用 dispatch_release(q); 释放相应的对象

◦                     dispatch_barrier 必须使用自定义的并发队列

◦                     开发第三方框架时,建议使用并发队列

全局队列异步任务

/**

提问:是否开线程?是否顺序执行?come here 的位置?

*/

- (void)gcdDemo8 {

// 1. 队列

dispatch_queue_t q = dispatch_get_global_queue(0, 0);

// 2. 执行任务

for (int i = 0; i < 10; ++i) {

dispatch_async(q, ^{

NSLog(@"%@ - %d", [NSThread currentThread], i);

});

}

NSLog(@"come here");

}

运行效果与并发队列相同

参数

  • 服务质量(队列对任务调度的优先级)/iOS 7.0 之前,是优先级

iOS 8.0(新增,暂时不能用,今年年底)

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, 未指定,可以和iOS 7.0 适配

iOS 7.0

DISPATCH_QUEUE_PRIORITY_HIGH 2 高优先级

DISPATCH_QUEUE_PRIORITY_DEFAULT 0 默认优先级

DISPATCH_QUEUE_PRIORITY_LOW (-2) 低优先级

DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN 后台优先级

  • 为未来保留使用的,应该永远传入0

结论:如果要适配 iOS 7.0 & 8.0,使用以下代码: dispatch_get_global_queue(0, 0);

step 4 GCD 队列演练的更多相关文章

  1. iOS边练边学--GCD的基本使用、GCD各种队列、GCD线程间通信、GCD常用函数、GCD迭代以及GCD队列组

    一.GCD的基本使用 <1>GCD简介 什么是GCD 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器” 纯C语言,提供了非常多强大的函数   GCD的优势 G ...

  2. 为GCD队列绑定NSObject类型上下文数据-利用__bridge_retained(transfer)转移内存管理权-备

    下面评论的好友“@Jim”给了种新的思路,就是在清除context的函数里面,用“_bridge_transfer”转换context,把context的内存管理权限重新交给ARC,这样,就不用显式调 ...

  3. enode框架step by step之消息队列的设计思路

    enode框架step by step之消息队列的设计思路 enode框架系列step by step文章系列索引: enode框架step by step之开篇 enode框架step by ste ...

  4. Swift3 GCD队列优先级说明

    从ios8开始,苹果引入了一个新的概念 QoS(quality of service),用于指定GCD队列的优先级. swift3之前:只有4个优先级 high > default > l ...

  5. OC - GCD 队列组 - 下载图片画图

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ [self downloadIma ...

  6. OC 线程操作 - GCD队列组

    1.队列组两种使用方法2.队列组等待 wait /** 新方法 队列组一般用在在异步操作,在主线程写队列组毫无任何作用 */ - (void)GCD_Group_new_group___notify{ ...

  7. 多线程 GCD队列组

    //  DYFViewController.m //  623-08-队列组 // //  Created by dyf on 14-6-23. //  Copyright (c) 2014年 ___ ...

  8. 数据存储_FMDB数据库队列

    一.代码示例 1.需要先导入FMDB框架和头文件,由于该框架依赖于libsqlite库,所以还应该导入该库. 2.代码如下: 1 // 2 // YYViewController.m 3 // 05- ...

  9. 4.3 多线程进阶篇<中>(GCD)

    更正:队列名称的作用的图中,箭头标注的有些问题,已修正 本文并非最终版本,如有更新或更正会第一时间置顶,联系方式详见文末 如果觉得本文内容过长,请前往本人 “简书” 本文源码 Demo 详见 Gith ...

随机推荐

  1. KVO内部实现原理

    KVO的原理: 只要给一个对象注册一个监听, 那么在运行时, 系统就会自动给该对象生成一个子类对象, (格式如:NSKVONotifying_className), 并且重写自动生成的子类对象的被监听 ...

  2. 57. Android之程序调试LogCat (转)

    无论什么样的程序开发过程中,出现错误都是不可避免的,一般情况下,语法错误会被开发环境检测到,并能及时的提示我们错误的位置以及修改的方法,但是逻辑错误就不是那么容易被发现了,通常逻辑错误的定位和分析是一 ...

  3. glyphicon halflings regular ttf 报错

    一个web项目 用了bootstrap chrome开f12报错提示glyphicon halflings regular ttf找不到 为什么找不到,肯定又是path出了问题 找到bootstrap ...

  4. ConvertHelper类

    /// <summary> /// 处理数据类型转换,数制转换.编码转换相关的类 /// </summary> public sealed class ConvertHelpe ...

  5. VMP虚拟机加壳的原理学习

    好久没有到博客写文章了,9月份开学有点忙,参加了一个上海的一个CHINA SIG信息比赛,前几天又无锡南京来回跑了几趟,签了阿里巴巴的安全工程师,准备11月以后过去实习,这之前就好好待在学校学习了. ...

  6. ObjC 巧用反射和KVC实现JSON快速反序列化成对象

    1.简单的KVC介绍 KVC是一种间接访问对象属性的机制,不直接调用getter 和 setter方法,而使用valueForKey 来替代getter 方法,setValue:forKey来代替se ...

  7. jpa和hibernate注解

    http://www.objectdb.com/api/java/jpa/JoinColumns 用hibernate和jpa annotation 大概一年多了,今天闲来无事,对他们关联关系元数据写 ...

  8. 提高SQL的查询效率

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引.   2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使 ...

  9. 爬虫例子及知识点(scrapy知识点)

    新知识: 新建一个scrapy项目:scrapy startproject xxx(项目名称) 运行一个scrapy项目:scrapy crawl xxx(项目名称) 项目文件说明: 文件说明: • ...

  10. html内容写入到文件中的时候出现‘TypeError: expected a character buffer object’错误

    代码如下: with open('ryf.md', 'a') as f: f.write(content) # content是html内容 原因是写入文件要求写入内容是str,直接转换成str即可, ...