Swift终于在5.x版本变得稳定,先来看看Swift5.1中的GCD如何使用
串行队列
串行队列一般只分配一个线程,队列如果有任务执行是不允许插队。
串行队列中执行任务的线程不允许被当前队列中的任务阻塞(死锁),但是能被其他对列阻塞
默认创建的是串行队列
let queue = DispatchQueue(label: "com.youdao.queueName") |
主线程就是串行队列
DispatchQueue.main |
常见的主线程死锁
//main Threed |
(并行队列) 并发队列
并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行。所以无论从微观还是从宏观来看,二者都是一起执行的。
并发(concurrency):指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行。
Erlang 之父 Joe Armstrong 的解释
创建并发队列
let taskD_queue = DispatchQueue.init(label: "com.youdao.concurrent", attributes: .concurrent) |
系统并发队列
let globalQueue = DispatchQueue.global() |
更多参数
public convenience init(label: String, qos: DispatchQoS = .unspecified, attributes: DispatchQueue.Attributes = [], |
qos
Quality of Service(服务质量)
队列执行有优先级,优先级由高到低
- userInteractive: 用户交互任务(例如动画,事件处理或更新应用程序的用户界面)的服务
- userInitiated:用户发起的动作需要立即得到结果 如打开文档,显示电子邮件
- default:默认的
- utility:用户不主动关注的,一些耗时操作。下载或者导入数据,utility任务一般有一个进度条让用户能看到
- background:最低优先级 后台运行。建立索引 清理文件
默认值为 default
还有一个特殊的unspecified
它表示当前没有QoS信息,系统应该根据环境自动推断QoS信息。如果使用遗弃的API,线程有可能会脱离QoS,这个时候,线程就是unspecified QoS类别的
因此系统并发队列有6个
let globalQueue1 = DispatchQueue.global(qos: .userInteractive) |
要注意,在Low Power Mode下,qos为background的队列将被暂停
attributes
//Set |
- concurrent:标记为并发队列
- initiallyInactive:标识队列中的任务需要手动触发,由队列activate()方法触发。未标记initiallyInactive的队列会自动触发任务
不标明此参数,默认是串行队列。
//串行队列 |
autoreleaseFrequency
autoreleaseFrequency是枚举,标明autoreleasepool的释放频率
public enum AutoreleaseFrequency { |
自己创建的队列,默认值是 .inherit
系统定义的全局队列,此属性是 .never
如果任务中需要大量创建对象,可以设置为.never,然后手动创建autoreleasepool
target
设置一个队列的目标队列,讲当前队列中的任务放到目标队列中取执行。目标队列最终约束了队列任务的优先级。
所有手动创建的队列,target最终都指向了系统自带的队列。主队列或者全局并发队列。
为什么不直接加到系统队列,而是要自定义队列呢?这样的好处是可以将任务分组管理。如单独阻塞某个队列中的任务,而不是阻塞系统队列中的全部任务。如果阻塞了系统队列,所有指向它的原队列也就被阻塞。
设置target可以在DispatchQueue初始化时候指定。
let task_queue = DispatchQueue.init(label: "abc", qos: .default, attributes: [.concurrent], autoreleaseFrequency: .workItem, target: DispatchQueue.global()) |
也可以指定attributes为.initiallyInactive。手动触发前使用setTarget更改指定的target
let task_queue = DispatchQueue.init(label: "abc", qos: .default, attributes: [.initiallyInactive, .concurrent], autoreleaseFrequency: .workItem, target: DispatchQueue.global()) |
可以思考下,下方代码会输出什么。
let task_queue = DispatchQueue.init(label: "abc", qos: .default, attributes: [.initiallyInactive, .concurrent], autoreleaseFrequency: .workItem, target: DispatchQueue.main) |
Group