我們都知道隊列有串行隊列和并發(fā)隊列畦徘,主隊列就屬于串行隊列,串行隊列里面的任務(wù)是按順序執(zhí)行旬陡,并發(fā)隊列里的任務(wù)是并發(fā)執(zhí)行拓颓,至于并發(fā)幾個線程去執(zhí)行,這就交給GCD 了描孟。
但是有個問題需要思考一下驶睦,我們都知道任務(wù)要執(zhí)行,先要從隊列中取出匿醒,然后再分配到線程中執(zhí)行场航,也就是分三步:1.從隊列中取出任務(wù),2.執(zhí)行任務(wù)廉羔,3.任務(wù)執(zhí)行完畢溉痢。所謂串行隊列里面的任務(wù)按順序執(zhí)行,這個按順序是指的按順序取出憋他,還是等前一個任務(wù)執(zhí)行完畢再執(zhí)行下一個任務(wù)呢孩饼?寫個代碼測試一下。
串行隊列同步異步執(zhí)行測試
1.串行隊列中同步執(zhí)行一個任務(wù)竹挡,異步執(zhí)行一個任務(wù)
let seralQueue = DispatchQueue(label: "dispatchSeralQueue")
//任務(wù)一
seralQueue.sync {
for i in 0...10 {
debugPrint("queueTest seralQueue1: \(Thread.current), \(i)")
}
}
//任務(wù)二
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"
可以看到镀娶,第一個任務(wù)是在主線程執(zhí)行,第二個任務(wù)在子線程執(zhí)行揪罕,這符合代碼邏輯梯码,從輸出順序上來看,在串行隊列中好啰,雖然任務(wù)二用了異步執(zhí)行的方式轩娶,也開了新的線程,但是順序卻是任務(wù)一執(zhí)行完畢之后框往,任務(wù)二才會執(zhí)行罢坝。
2.串行隊列中異步執(zhí)行兩個任務(wù)
let seralQueue = DispatchQueue(label: "dispatchSeralQueue")
// 任務(wù)一
seralQueue.async {
for i in 0...5 {
debugPrint("queueTest seralQueue1: \(Thread.current), \(i)")
}
}
//任務(wù) 二
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"
可以看到,兩個任務(wù)都在子線程執(zhí)行搅窿,而且是按順序的嘁酿,第一個任務(wù)執(zhí)行完畢,才會輪到第二個任務(wù)執(zhí)行男应。
3.串行隊列同步執(zhí)行兩個任務(wù)
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"
同步執(zhí)行順序隊列任務(wù)闹司,沒有開啟新線程,任務(wù)按順序執(zhí)行沐飘。
并發(fā)隊列同步異步執(zhí)行測試
并發(fā)隊列異步執(zhí)行兩個任務(wù)
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"
可以看到兩個任務(wù)之間是交叉執(zhí)行的游桩,并沒有順序關(guān)系,而且也開辟了新的線程耐朴。
并發(fā)隊列同步執(zhí)行兩個任務(wù)
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"
可以看到并發(fā)隊列同步執(zhí)行借卧,并沒有開啟新的線程,任務(wù)也是按順序執(zhí)行完畢的
并發(fā)隊列中筛峭,同步執(zhí)行一個任務(wù)铐刘,異步執(zhí)行一個任務(wù)
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"
異步執(zhí)行的任務(wù)開啟了新的線程,但是兩個任務(wù)之間還是順序的關(guān)系影晓,一個任務(wù)執(zhí)行完畢镰吵,才會開始執(zhí)行下一個任務(wù)。
結(jié)論
串行隊列+同步執(zhí)行=不開新線程挂签,任務(wù)依次執(zhí)行
串行隊列+異步執(zhí)行=開啟新線程疤祭,任務(wù)依次執(zhí)行
并發(fā)隊列+同步執(zhí)行=不開新線程,任務(wù)依次執(zhí)行
并發(fā)隊列+異步執(zhí)行=開啟新線程饵婆,任務(wù)并發(fā)執(zhí)行