之前有写过关于 GCD的东西(地址),但是最近又把自己弄迷糊了.所以有在 swift3.0的语法下重新理解一下关于串行并行同步异步的概念
关于 Swift3.0下 GCD的使用方法这里就不写了,不了解的可以看这里Swift 3 中的 GCD 与 Dispatch Queue
重新理解之后,我发现之前看过的相关文章都没有把一个大前提告诉我,导致我在各个概念之间迷糊~~~
大前提: 我们这里说的串行同步
串行异步
并行同步
并行异步
都是针对一个队列的多个任务
来说明的,只有先认清这个前提,才能很好的理解这几个概念,而不至于在串行、并行、同步、异步之间晕头转向.之后详解多个队列也就很容易了.
一个队列下多个任务的串行同步
// 串行同步
func syncSample(){
let queue = DispatchQueue(label: "com.zhengwenxiang")
queue.sync {
for i in 0..<10{
print(" ", i)
}
print("current thread is \(Thread.current)")
}
queue.sync {
for i in 20..<30{
print(" ", i)
}
print("current thread02 is \(Thread.current)")
}
for i in 100..<110{
print(" ", i)
}
print("Main thread is \(Thread.current)")
}
从输出结果不难看出,队列 queue和主队列在同一个线程上按照出现顺序依次执行(主线程),很显然 queue队列的两个任务堵塞了主线程
我们不妨想象一个场景: 一个 iPhone 生产工厂,只有一条正在运营的生产线,生产线上有着一步一步待组装的 iPhone 元件(工厂就是当前程序,这条生产线就是主线程,元件就是任务,也就是block).
当我们创建一个串行同步队列,里面放入两个任务,例如上面代码queue.sync{}
,所谓串行就是按顺序执行,所谓同步就是在当前线程中执行
.所以,当我们创建一个串行同步队列时,就相当于在上面正在运营的供产线上插入一个包含多个元件的包,本来正在运行的生产线走到这里后,按顺序处理完这个包里的元件再继续向下执行,直至结束.
这里的要点是: 没有创建新的生产线,仅仅是在已有的生产线的塞入几个任务
需要谨记的是: 同步:在当前线程中执行 。异步:在另一条线程中执行
一个队列下多个任务的串行异步
// 串行异步
func asyncSample(){
let queue = DispatchQueue(label: "com.zhengwenxiang")
queue.async {
for i in 0..<10{
print(" ", i)
}
print("current thread is \(Thread.current)")
}
queue.async {
for i in 20..<30{
print(" ", i)
}
print("current thread02 is \(Thread.current)")
}
for i in 100..<110{
print(" ", i)
}
print("Main thread is \(Thread.current)")
}
看结果:很好的印证了上面的话.异步会创建新线程.串行异步只有创建一条新线程.
同样是上面的场景,现在在生产线上放上了一个包含两个元件的元件包.但是当前生产线无法打开这个包,于是就新建立老板就新建了一条生成先专门处理这类包的生产线,遇到这种包就把它扔到这条生产线上,原来生产线继续执行不去管这个包继续往下执行,这个包到新生产线上呗打开然后按顺序组装,至于这个包里的两个元件什么时候组装完成,已经与原来生产线的的元件哪个先组装完成我们就没法知道..唯一可以确定的是新生成线上的两个元件,一定是元件1组装完成之后再组装元件2.
一个队列下多个任务的并行同步
// 并行同步
func conQueueSyncSample(){
/*
这个 attributes 参数也可以接受另一个名为 initiallyInactive 的值。如果使用这个值,任务不会被自动执行,而是需要开发者手动去触发。
*/
let anotherQueue = DispatchQueue(label: "com.zhengwenxiang.con", qos: .utility, attributes: .concurrent)
//initiallyInactive属性的串行队列
// let anotherQueue = DispatchQueue(label: "com.zhengwenxiang.con", qos: .utility, attributes: .initiallyInactive)
// initiallyInactive属性的并行队列
// let anotherQueue = DispatchQueue(label: "com.zhengwenxiang.con", qos: .utility, attributes: [.concurrent, .initiallyInactive])
// inactiveQueue = anotherQueue
anotherQueue.sync {
for i in 0..<10{
print(" ", i)
}
print("current thread is \(Thread.current)")
}
anotherQueue.sync {
for i in 100..<110{
print(" ", i)
}
print("current thread02 is \(Thread.current)")
}
显然,同步不创建新线程,结果与串行同步一样...我没想通并行同步的意义,可能只是因为并行异步才应运而生的吧
一个队列下多个任务的并行异步
// 并行异步
func conQueueAsyncSample(){
//let anotherQueue = DispatchQueue(label: "com.zhengwenxiang.con", qos: .utility)
/*
这个 attributes 参数也可以接受另一个名为 initiallyInactive 的值。如果使用这个值,任务不会被自动执行,而是需要开发者手动去触发。
*/
let anotherQueue = DispatchQueue(label: "com.zhengwenxiang.con", qos: .utility, attributes: .concurrent)
anotherQueue.async {
for i in 0..<10{
print(" ", i)
}
print("current thread is \(Thread.current)")
}
anotherQueue.async {
for i in 100..<110{
print(" ", i)
}
print("current thread02 is \(Thread.current)")
}
// anotherQueue.async {
// for i in 1000..<1010 {
// print(" ", i)
// }
// }
for i in 2000..<2010 {
print(" ", i)
}
print("Main thread is \(Thread.current)")
}
异步创建新线程,从截图我可以看到,一个有三条线程,一条主线程和两条新线程.
可以想象的是,正如串行一不一样,遇到一个包含 n 个元件的包,当前生产线打不开,老大有钱了,就豪掷千金又给工程装了几条生产线,但是毕竟资金有限, b 不宜装太大,所以不能再新建 n 条生产线,根据实际情况装了几条生产线,装个小 b. 然后把包里的 n 个元件扔到新建的生产线上进行装装同样我们我们也没法主动包里的元件与原来生产线上的元件谁先组装完成.**当然,具体完成顺序可以可控,我们通过给队列设置优先级来控制,比如上面代码,我们设置了anotherQueue队列的优先级是utility(具体优先级设置可以自己查询),所有这里我们的主线程总是在两个新线程前完成组装 **
PS: 具体延伸多个队列的详情,可以通过运行 demo了解,相信上面理解了就能理解.
GCDDemo地址