关于GCD基础知识的文章很多,但很多都停留在iOS早期版本的状态,随着iOS的升级GCD的使用也随之升级了,下面举了很多例子来看一看。

1、串行队列使用同步运行

1、普通队列同步运行
let queue = DispatchQueue(label:"com.test")
queue.sync{for _ in 0..<6 {print("aaaaaaa\(Thread.current)")}
}
for _ in 0..<6  {print("bbbbbbb\(Thread.current)")
}  

运行结果:

aaaaaaa<NSThread: 0x6040002608c0>{number = 1, name = main}

aaaaaaa<NSThread: 0x6040002608c0>{number = 1, name = main}

aaaaaaa<NSThread: 0x6040002608c0>{number = 1, name = main}

aaaaaaa<NSThread: 0x6040002608c0>{number = 1, name = main}

aaaaaaa<NSThread: 0x6040002608c0>{number = 1, name = main}

aaaaaaa<NSThread: 0x6040002608c0>{number = 1, name = main}

bbbbbbb<NSThread: 0x6040002608c0>{number = 1, name = main}

bbbbbbb<NSThread: 0x6040002608c0>{number = 1, name = main}

bbbbbbb<NSThread: 0x6040002608c0>{number = 1, name = main}

bbbbbbb<NSThread: 0x6040002608c0>{number = 1, name = main}

bbbbbbb<NSThread: 0x6040002608c0>{number = 1, name = main}

bbbbbbb<NSThread: 0x6040002608c0>{number = 1, name = main}

结果分析:

串行队形完全阻断了主线程的运行,都使用main线程,这种写法是完全没有意义的。

2、串行队列使用异步运行

//2、普通队列异步运行
let queue = DispatchQueue(label:"com.test")
queue.async{for _ in 0..<6 {print("aaaaaaa\(Thread.current)")}
}
for _ in 0..<6  {print("bbbbbbb\(Thread.current)")
}

运行结果:

bbbbbbb<NSThread: 0x604000066580>{number = 1, name = main}

aaaaaaa<NSThread: 0x600000071680>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x600000071680>{number = 3, name = (null)}

bbbbbbb<NSThread: 0x604000066580>{number = 1, name = main}

aaaaaaa<NSThread: 0x600000071680>{number = 3, name = (null)}

bbbbbbb<NSThread: 0x604000066580>{number = 1, name = main}

bbbbbbb<NSThread: 0x604000066580>{number = 1, name = main}

bbbbbbb<NSThread: 0x604000066580>{number = 1, name = main}

bbbbbbb<NSThread: 0x604000066580>{number = 1, name = main}

aaaaaaa<NSThread: 0x600000071680>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x600000071680>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x600000071680>{number = 3, name = (null)}

运行结果分析:

串行队列任务与主线程并行,串行队列使用了新的线程3,感觉上就像自己启了一个线程在做事情,使用DispatchQueue会方便很多。

3、串行队列多次运行

//3、普通队列异步运行多次
let queue = DispatchQueue(label:"com.test",qos:DispatchQoS.unspecified)
queue.async{for _ in 0..<6 {print("aaaaaaa\(Thread.current)")}
}
queue.async{for _ in 0..<6 {print("cccccc\(Thread.current)")}
}
for _ in 0..<6  {print("bbbbbbb\(Thread.current)")
}

运行结果:

bbbbbbb<NSThread: 0x60400007cc40>{number = 1, name = main}

aaaaaaa<NSThread: 0x604000264a80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x604000264a80>{number = 3, name = (null)}

bbbbbbb<NSThread: 0x60400007cc40>{number = 1, name = main}

bbbbbbb<NSThread: 0x60400007cc40>{number = 1, name = main}

aaaaaaa<NSThread: 0x604000264a80>{number = 3, name = (null)}

bbbbbbb<NSThread: 0x60400007cc40>{number = 1, name = main}

aaaaaaa<NSThread: 0x604000264a80>{number = 3, name = (null)}

bbbbbbb<NSThread: 0x60400007cc40>{number = 1, name = main}

bbbbbbb<NSThread: 0x60400007cc40>{number = 1, name = main}

aaaaaaa<NSThread: 0x604000264a80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x604000264a80>{number = 3, name = (null)}

cccccc<NSThread: 0x604000264a80>{number = 3, name = (null)}

cccccc<NSThread: 0x604000264a80>{number = 3, name = (null)}

cccccc<NSThread: 0x604000264a80>{number = 3, name = (null)}

cccccc<NSThread: 0x604000264a80>{number = 3, name = (null)}

cccccc<NSThread: 0x604000264a80>{number = 3, name = (null)}

cccccc<NSThread: 0x604000264a80>{number = 3, name = (null)}

运行结果分析:

队形中任务与主线程并行且使用了新的线程3,这里可以看处理,串行队列只有等第一个任务运行完才执行第二个(所以aaaaaa打印完,才有cccccc),这里例子很适合做并发中互斥操作,不使用锁。

4、并行队列异步运行多次

//4、并行队列异步运行多次
let queue = DispatchQueue(label:"com.test",qos:DispatchQoS.unspecified,attributes:.concurrent)
queue.async{for _ in 0..<6 {print("aaaaaaa\(Thread.current)")}
}
queue.async{for _ in 0..<6 {print("cccccc\(Thread.current)")}
}
for _ in 0..<6  {print("bbbbbbb\(Thread.current)")
}  

运行结果:

bbbbbbb<NSThread: 0x604000079c00>{number = 1, name = main}

aaaaaaa<NSThread: 0x6040002657c0>{number = 4, name = (null)}

cccccc<NSThread: 0x600000267380>{number = 3, name = (null)}

bbbbbbb<NSThread: 0x604000079c00>{number = 1, name = main}

aaaaaaa<NSThread: 0x6040002657c0>{number = 4, name = (null)}

cccccc<NSThread: 0x600000267380>{number = 3, name = (null)}

bbbbbbb<NSThread: 0x604000079c00>{number = 1, name = main}

cccccc<NSThread: 0x600000267380>{number = 3, name = (null)}

bbbbbbb<NSThread: 0x604000079c00>{number = 1, name = main}

aaaaaaa<NSThread: 0x6040002657c0>{number = 4, name = (null)}

bbbbbbb<NSThread: 0x604000079c00>{number = 1, name = main}

bbbbbbb<NSThread: 0x604000079c00>{number = 1, name = main}

cccccc<NSThread: 0x600000267380>{number = 3, name = (null)}

cccccc<NSThread: 0x600000267380>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x6040002657c0>{number = 4, name = (null)}

cccccc<NSThread: 0x600000267380>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x6040002657c0>{number = 4, name = (null)}

aaaaaaa<NSThread: 0x6040002657c0>{number = 4, name = (null)}

运行结果分析:

并行队列的2个任务与主线程同时运行,并行队列中任务分别使用线程3和线程4,这是一个并发的场景,比如我们一边加载不同图片一边不会影响UI的响应;这里也可以看出串行队列与并行队列的不同之处。

5、多个串行队列异步运行

let queue = DispatchQueue(label:"com.test",qos:DispatchQoS.unspecified)
let queue2 = DispatchQueue(label:"com.test",qos:DispatchQoS.userInteractive)
queue.async{for _ in 0..<16 {print("aaaaaaa\(Thread.current)")}
}
queue2.async{for _ in 0..<16 {print("cccccc\(Thread.current)")}
}

运行结果:

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

运行结果分析:

例子中队列2的优先级比队列1高,所以cccccc在aaaaaa之前打印完,2个不同的串行队列使用不同的线程3和4,并行队列的优先级比较也是一样的结果,这里就不发例子

6、使用DispatchGroup做任务依赖

queue先做一个短任务,并行的queue2做一个长任务,等2个任务都做完group通知queue接着做任务,任务C依赖与任务A和任务B同时完成。

let queue = DispatchQueue(label:"com.test",qos:DispatchQoS.unspecified)
let queue2 = DispatchQueue(label:"com.test",qos:DispatchQoS.userInteractive)
let group = DispatchGroup()
queue.async(group: group, execute: {for _ in 0..<3 {print("aaaaaaa\(Thread.current)")}
})
queue2.async(group: group, execute: {for _ in 0..<6 {print("bbbbb\(Thread.current)")}
})//执行完上面的两个耗时操作, 回到queue队列中执行下一步的任务
group.notify(queue: queue) {print("回到queue该队列中执行")for _ in 0..<3 {print("bbbbb\(Thread.current)")}
}

运行结果:

bbbbb<NSThread: 0x604000078540>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x604000078580>{number = 4, name = (null)}

bbbbb<NSThread: 0x604000078540>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x604000078580>{number = 4, name = (null)}

bbbbb<NSThread: 0x604000078540>{number = 3, name = (null)}

aaaaaaa<NSThread: 0x604000078580>{number = 4, name = (null)}

bbbbb<NSThread: 0x604000078540>{number = 3, name = (null)}

bbbbb<NSThread: 0x604000078540>{number = 3, name = (null)}

bbbbb<NSThread: 0x604000078540>{number = 3, name = (null)}

回到queue该队列中执行

cccccc<NSThread: 0x604000078580>{number = 4, name = (null)}

cccccc<NSThread: 0x604000078580>{number = 4, name = (null)}

cccccc<NSThread: 0x604000078580>{number = 4, name = (null)}

运行结果分析:

2任务分别运行做线程3和4,等他们都做完再到queue中打印cccccc

7、使用DispatchGroup做任务等待

queue和queue2是2个并行的队列,queue2中sleep(UInt32(3))可以让queue2超时

let queue = DispatchQueue(label:"com.test",qos:DispatchQoS.unspecified)
let queue2 = DispatchQueue(label:"com.test",qos:DispatchQoS.userInteractive)
let group = DispatchGroup()
queue.async(group: group, execute: {for _ in 0..<3 {print("aaaaaaa\(Thread.current)")}
})
queue2.async(group: group, execute: {for _ in 0..<6 {print("bbbbb\(Thread.current)")}//sleep(UInt32(3))
})//等待上面任务执行,会阻塞当前线程,超时就执行下面的,上面的继续执行。可以无限等待 .distantFuture
let result:DispatchTimeoutResult = group.wait(timeout: .now() + 2.0)
switch result {
case .success:print("不超时, 上面的两个任务都执行完")
case .timedOut:print("超时了, 上面的任务还没执行完执行这了")
}print("接下来的操作")

  

打开sleep(UInt32(3)) 的结果:

aaaaaaa<NSThread: 0x604000273140>{number = 4, name = (null)}
bbbbb<NSThread: 0x6000004703c0>{number = 3, name = (null)}
aaaaaaa<NSThread: 0x604000273140>{number = 4, name = (null)}
bbbbb<NSThread: 0x6000004703c0>{number = 3, name = (null)}
bbbbb<NSThread: 0x6000004703c0>{number = 3, name = (null)}
bbbbb<NSThread: 0x6000004703c0>{number = 3, name = (null)}
aaaaaaa<NSThread: 0x604000273140>{number = 4, name = (null)}
bbbbb<NSThread: 0x6000004703c0>{number = 3, name = (null)}
bbbbb<NSThread: 0x6000004703c0>{number = 3, name = (null)}
超时了, 上面的任务还没执行完执行这了
接下来的操作

注解sleep(UInt32(3))结果:

bbbbb<NSThread: 0x604000273280>{number = 3, name = (null)}
aaaaaaa<NSThread: 0x600000278e00>{number = 4, name = (null)}
aaaaaaa<NSThread: 0x600000278e00>{number = 4, name = (null)}
bbbbb<NSThread: 0x604000273280>{number = 3, name = (null)}
aaaaaaa<NSThread: 0x600000278e00>{number = 4, name = (null)}
bbbbb<NSThread: 0x604000273280>{number = 3, name = (null)}
bbbbb<NSThread: 0x604000273280>{number = 3, name = (null)}
bbbbb<NSThread: 0x604000273280>{number = 3, name = (null)}
bbbbb<NSThread: 0x604000273280>{number = 3, name = (null)}
不超时, 上面的两个任务都执行完
接下来的操作

结果分析:

可以用Group的wait方法来做超时判断。

ps:例子多了点,都是一个一个字码的,系统对学习Swift的GCD有用。

转载于:https://www.cnblogs.com/sakaiPeng/p/9808733.html

用例子看Swift4的GCD相关推荐

  1. 一个简单的例子看java线程机制

    一个简单的例子看java线程机制 作者: zyf0808 发表日期: 2006-03-26 11:20 文章属性: 原创 复制链接 import java.util.*; public class T ...

  2. 抽象语法树 c语言,一个简单的例子看懂抽象语法树的魔力

    在计算机科学中,抽象语法树(Abstract Syntax Tree,AST),或简称语法树(Syntax tree),是源代码语法结构的一种抽象表示.它以树状的形式表现编程语言的语法结构,树上的每个 ...

  3. 从一个小例子看贝叶斯公式的应用(学习简单、基础、入门的例子)

    #从一个小例子看贝叶斯公式的应用 ###应用Bayesian公式考察如下的实例并回答问题. 张某为了解自己患上了X疾病的可能性,去医院作常规血液检查.其结果居然为阳性,他赶忙到网上查询.根据网上的资料 ...

  4. 通过几个例子看sed的模式空间与保持空间

    SED之所以能以行为单位的编辑或修改文本,其原因在于它使用了两个空间:一个是活动的"模式空间(pattern space)",另一个是起辅助作用的"暂存缓冲区(holdi ...

  5. 从一个微型例子看“C/C++的内存分配机制”和“数组变量名与指针变量名”

    内存分配方式有三种: 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. 在栈上创建. 在执行函数时,函数内局部变量的存储单元都 ...

  6. 见微智著 - 从一个小例子看Python中的单元测试

    单元测试 据统计,由于软件缺陷(bug),美国经济每年在浪费生产力.返工和实际毁坏上损失了数十亿美元.近期最严重的案例是波音737 Max飞机的两次重大坠机事故,共造成了346人死亡.经过初步调查,该 ...

  7. 《Spring事务传播行为详解》经典例子 看完这篇,别的不用看了

    前言 Spring在TransactionDefinition接口中规定了7种类型的事务传播行为.事务传播行为是Spring框架独有的事务增强特性,他不属于的事务实际提供方数据库行为.这是Spring ...

  8. Swift4 使用GCD实现计时器

    开发过程中,我们可能会经常使用到计时器.苹果为我们提供了Timer.但是在平时使用过程中会发现使用Timer会有许多的不便 1:必须保证在一个活跃的runloop,我们知道主线程的runloop是活跃 ...

  9. 一个例子看懂kotlin的集合和序列

    构造对比: 1.集合 这里setOf和mutableSetOf就是一个只读,一个支持修改处理.因为集合泛型的擦除,val和var其实不能控制只读和读写.故用这种构造方法. // 挨个元素传入 val ...

最新文章

  1. [高级]android应用开发之intent的妙用二
  2. 雅虎公司C#笔试题,看看你能解答多少? [含答案]
  3. java pdf添加图片_java实现在pdf模板的指定位置插入图片
  4. 密码学基础知识(六)Hash函数与消息认证
  5. [论文学习]Manifold Mixup和PatchUp的代码重新实现(实现即插即用且速度更快)
  6. python调用其它文件函数或类
  7. java perl5compiler,Java中正则表达式使用方法详解(四)
  8. qt调用mysql调用了存储过_Qt调用Server SQL中的存储过程
  9. 使用ListBox控件来实现直方图控件(一)
  10. resnet的瓶颈层的子层res4b22的命名规则
  11. java工程展示问题
  12. iOS 图片裁剪功能。
  13. 网站seo优化到底该怎么做?
  14. 怎么样把自己计算机两个硬盘合并,两个硬盘怎么合并成一个盘
  15. R数据分析——回归分析
  16. 高数笔记(十九):对面积的曲面积分,对坐标的曲面积分,高斯公式,斯托克斯公式
  17. LeetCode面试热题十二
  18. Docker容器的数据卷(volumes)
  19. 如何找到一个应用的源代码
  20. 2018个人年终总结

热门文章

  1. 可能存在无限递归_无限分类递归+排序解剖
  2. 交通流预测python代码_Python 3 amp; Keras 实现基于神经网络的交通流预测
  3. python画图哆啦a梦大作业_Python—turtle画图(哆啦A梦)
  4. linux重装系统u盘启动不了怎么办,U盘安装Linux开机无法启动解决方法
  5. android平台安全支付服务(msp)应用开发接口,Android接入支付宝和微信支付的方法...
  6. C语言霍夫曼编码压缩,数据结构大作业——哈夫曼编码压缩BMP格式文件
  7. php 解析lrc文件格式,PHP - 四级单词lrc文件解析为txt
  8. kvm虚拟机设置万兆网卡_kvm已经设置桥接网卡的虚拟机无法连接宿主机?
  9. php wiki搭建,wiki网站搭建
  10. 自己构建React项目