iOS 的串行队列和并发队列中的任务是如何执行的
2021-11-21 本文已影响0人
栋柠柒
我们都知道队列有串行队列和并发队列,主队列就属于串行队列,串行队列里面的任务是按顺序执行,并发队列里的任务是并发执行,至于并发几个线程去执行,这就交给GCD 了。
但是有个问题需要思考一下,我们都知道任务要执行,先要从队列中取出,然后再分配到线程中执行,也就是分三步:1.从队列中取出任务,2.执行任务,3.任务执行完毕。所谓串行队列里面的任务按顺序执行,这个按顺序是指的按顺序取出,还是等前一个任务执行完毕再执行下一个任务呢?写个代码测试一下。
串行队列同步异步执行测试
1.串行队列中同步执行一个任务,异步执行一个任务
let seralQueue = DispatchQueue(label: "dispatchSeralQueue")
//任务一
seralQueue.sync {
for i in 0...10 {
debugPrint("queueTest seralQueue1: \(Thread.current), \(i)")
}
}
//任务二
seralQueue.async {
for i in 0...10 {
debugPrint("queueTest seralQueue2: \(Thread.current), \(i)")
}
}
"queueTest seralQueue1: <_NSMainThread: 0x600002360540>{number = 1, name = main}, 0"
"queueTest seralQueue1: <_NSMainThread: 0x600002360540>{number = 1, name = main}, 1"
"queueTest seralQueue1: <_NSMainThread: 0x600002360540>{number = 1, name = main}, 2"
"queueTest seralQueue1: <_NSMainThread: 0x600002360540>{number = 1, name = main}, 3"
"queueTest seralQueue1: <_NSMainThread: 0x600002360540>{number = 1, name = main}, 4"
"queueTest seralQueue1: <_NSMainThread: 0x600002360540>{number = 1, name = main}, 5"
"queueTest seralQueue2: <NSThread: 0x60000235eec0>{number = 4, name = (null)}, 0"
"queueTest seralQueue2: <NSThread: 0x60000235eec0>{number = 4, name = (null)}, 1"
"queueTest seralQueue2: <NSThread: 0x60000235eec0>{number = 4, name = (null)}, 2"
"queueTest seralQueue2: <NSThread: 0x60000235eec0>{number = 4, name = (null)}, 3"
"queueTest seralQueue2: <NSThread: 0x60000235eec0>{number = 4, name = (null)}, 4"
"queueTest seralQueue2: <NSThread: 0x60000235eec0>{number = 4, name = (null)}, 5"
可以看到,第一个任务是在主线程执行,第二个任务在子线程执行,这符合代码逻辑,从输出顺序上来看,在串行队列中,虽然任务二用了异步执行的方式,也开了新的线程,但是顺序却是任务一执行完毕之后,任务二才会执行。
2.串行队列中异步执行两个任务
let seralQueue = DispatchQueue(label: "dispatchSeralQueue")
// 任务一
seralQueue.async {
for i in 0...5 {
debugPrint("queueTest seralQueue1: \(Thread.current), \(i)")
}
}
//任务 二
seralQueue.async {
for i in 0...5 {
debugPrint("queueTest seralQueue2: \(Thread.current), \(i)")
}
}
"queueTest seralQueue1: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 0"
"queueTest seralQueue1: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 1"
"queueTest seralQueue1: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 2"
"queueTest seralQueue1: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 3"
"queueTest seralQueue1: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 4"
"queueTest seralQueue1: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 5"
"queueTest seralQueue2: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 0"
"queueTest seralQueue2: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 1"
"queueTest seralQueue2: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 2"
"queueTest seralQueue2: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 3"
"queueTest seralQueue2: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 4"
"queueTest seralQueue2: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 5"
可以看到,两个任务都在子线程执行,而且是按顺序的,第一个任务执行完毕,才会轮到第二个任务执行。
3.串行队列同步执行两个任务
let seralQueue = DispatchQueue(label: "dispatchSeralQueue")
seralQueue.sync {
for i in 0...5 {
debugPrint("queueTest seralQueue1: \(Thread.current), \(i)")
}
}
seralQueue.sync {
for i in 0...5 {
debugPrint("queueTest seralQueue2: \(Thread.current), \(i)")
}
}
"queueTest seralQueue1: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 0"
"queueTest seralQueue1: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 1"
"queueTest seralQueue1: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 2"
"queueTest seralQueue1: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 3"
"queueTest seralQueue1: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 4"
"queueTest seralQueue1: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 5"
"queueTest seralQueue2: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 0"
"queueTest seralQueue2: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 1"
"queueTest seralQueue2: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 2"
"queueTest seralQueue2: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 3"
"queueTest seralQueue2: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 4"
"queueTest seralQueue2: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 5"
同步执行顺序队列任务,没有开启新线程,任务按顺序执行。
并发队列同步异步执行测试
并发队列异步执行两个任务
let conCurrentQueue = DispatchQueue(label: "dispatchConcurrentQueue", attributes: .concurrent)
conCurrentQueue.async {
for i in 0...5 {
debugPrint("queueTest conCurrentQueue1: \(Thread.current), \(i)")
}
}
conCurrentQueue.async {
for i in 0...5 {
debugPrint("queueTest conCurrentQueue2: \(Thread.current), \(i)")
}
}
"queueTest conCurrentQueue2: <NSThread: 0x60000018e780>{number = 5, name = (null)}, 0"
"queueTest conCurrentQueue1: <NSThread: 0x600000189e80>{number = 6, name = (null)}, 0"
"queueTest conCurrentQueue2: <NSThread: 0x60000018e780>{number = 5, name = (null)}, 1"
"queueTest conCurrentQueue1: <NSThread: 0x600000189e80>{number = 6, name = (null)}, 1"
"queueTest conCurrentQueue2: <NSThread: 0x60000018e780>{number = 5, name = (null)}, 2"
"queueTest conCurrentQueue1: <NSThread: 0x600000189e80>{number = 6, name = (null)}, 2"
"queueTest conCurrentQueue2: <NSThread: 0x60000018e780>{number = 5, name = (null)}, 3"
"queueTest conCurrentQueue1: <NSThread: 0x600000189e80>{number = 6, name = (null)}, 3"
"queueTest conCurrentQueue2: <NSThread: 0x60000018e780>{number = 5, name = (null)}, 4"
"queueTest conCurrentQueue1: <NSThread: 0x600000189e80>{number = 6, name = (null)}, 4"
"queueTest conCurrentQueue2: <NSThread: 0x60000018e780>{number = 5, name = (null)}, 5"
"queueTest conCurrentQueue1: <NSThread: 0x600000189e80>{number = 6, name = (null)}, 5"
可以看到两个任务之间是交叉执行的,并没有顺序关系,而且也开辟了新的线程。
并发队列同步执行两个任务
conCurrentQueue.sync {
for i in 0...5 {
debugPrint("queueTest conCurrentQueue1: \(Thread.current), \(i)")
}
}
conCurrentQueue.sync {
for i in 0...5 {
debugPrint("queueTest conCurrentQueue2: \(Thread.current), \(i)")
}
}
"queueTest conCurrentQueue1: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 0"
"queueTest conCurrentQueue1: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 1"
"queueTest conCurrentQueue1: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 2"
"queueTest conCurrentQueue1: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 3"
"queueTest conCurrentQueue1: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 4"
"queueTest conCurrentQueue1: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 5"
"queueTest conCurrentQueue2: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 0"
"queueTest conCurrentQueue2: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 1"
"queueTest conCurrentQueue2: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 2"
"queueTest conCurrentQueue2: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 3"
"queueTest conCurrentQueue2: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 4"
"queueTest conCurrentQueue2: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 5"
可以看到并发队列同步执行,并没有开启新的线程,任务也是按顺序执行完毕的
并发队列中,同步执行一个任务,异步执行一个任务
let conCurrentQueue = DispatchQueue(label: "dispatchConcurrentQueue", attributes: .concurrent)
conCurrentQueue.sync {
for i in 0...5 {
debugPrint("queueTest conCurrentQueue1: \(Thread.current), \(i)")
}
}
conCurrentQueue.async {
for i in 0...5 {
debugPrint("queueTest conCurrentQueue2: \(Thread.current), \(i)")
}
}
"queueTest conCurrentQueue1: <_NSMainThread: 0x600000d6c000>{number = 1, name = main}, 0"
"queueTest conCurrentQueue1: <_NSMainThread: 0x600000d6c000>{number = 1, name = main}, 1"
"queueTest conCurrentQueue1: <_NSMainThread: 0x600000d6c000>{number = 1, name = main}, 2"
"queueTest conCurrentQueue1: <_NSMainThread: 0x600000d6c000>{number = 1, name = main}, 3"
"queueTest conCurrentQueue1: <_NSMainThread: 0x600000d6c000>{number = 1, name = main}, 4"
"queueTest conCurrentQueue1: <_NSMainThread: 0x600000d6c000>{number = 1, name = main}, 5"
"queueTest conCurrentQueue2: <NSThread: 0x600000d24d40>{number = 7, name = (null)}, 0"
"queueTest conCurrentQueue2: <NSThread: 0x600000d24d40>{number = 7, name = (null)}, 1"
"queueTest conCurrentQueue2: <NSThread: 0x600000d24d40>{number = 7, name = (null)}, 2"
"queueTest conCurrentQueue2: <NSThread: 0x600000d24d40>{number = 7, name = (null)}, 3"
"queueTest conCurrentQueue2: <NSThread: 0x600000d24d40>{number = 7, name = (null)}, 4"
"queueTest conCurrentQueue2: <NSThread: 0x600000d24d40>{number = 7, name = (null)}, 5"
异步执行的任务开启了新的线程,但是两个任务之间还是顺序的关系,一个任务执行完毕,才会开始执行下一个任务。
结论
串行队列+同步执行=不开新线程,任务依次执行
串行队列+异步执行=开启新线程,任务依次执行
并发队列+同步执行=不开新线程,任务依次执行
并发队列+异步执行=开启新线程,任务并发执行