GCD 一直以來是基于 c 語言的救拉。
apple 為了使 GCD 使用更加的 swift 化。 對 GCD 進行了進行了改造瘫拣。
以下所有代碼都是基于 Swift3.0
先來段廢話:
(不了解基本概念的建議看看近上, 了解的直接略過!)
GCD
Grand Central Dispatch (GCD)是Apple開發(fā)的一個多核編程的較新的解決方法。它主要用于優(yōu)化應(yīng)用程序以支持多核處理器以及其他對稱多處理系統(tǒng)壹无。它是一個在線程池模式的基礎(chǔ)上執(zhí)行的并行任務(wù)。在Mac OS X 10.6雪豹中首次推出感帅,也可在IOS 4及以上版本使用斗锭。
GCD 中兩個重要重要概念 —— 隊列 & 任務(wù)
隊列
隊列是一種特殊的線性表,采用FIFO(先進先出)的原則失球,即新任務(wù)總是被插入到隊列的末尾岖是,而讀取任務(wù)的時候總是從隊列的頭部開始讀取。每讀取一個任務(wù)实苞,則從隊列中釋放一個任務(wù)豺撑。
隊列的主要作用是用來存放任務(wù)。
GCD會自動將隊列中的任務(wù)取出黔牵,放到對應(yīng)的線程中執(zhí)行聪轿。
**隊列分類: **
串行隊列(Serial Dispatch Queue): 讓任務(wù)一個接著一個地執(zhí)行(一個任務(wù)執(zhí)行完畢后,再執(zhí)行下一個任務(wù)
并發(fā)隊列(Concurrent Dispatch Queue): 可以讓多個任務(wù)并發(fā)(同時)執(zhí)行(自動開啟多個線程同時執(zhí)行任務(wù)), 并發(fā)功能只有在異步(dispatch_async)函數(shù)下才有效
> 由于隊列同步執(zhí)行不具有開啟線程的能力猾浦,異步執(zhí)行才可以開啟線程陆错。
> 并發(fā)隊列在異步執(zhí)行才有效。
隊列執(zhí)行任務(wù)的方式:
同步:在當(dāng)前線程中執(zhí)行金赦,當(dāng)前代碼不執(zhí)行完音瓷,就不能夠執(zhí)行下一條代碼。會阻塞當(dāng)前線程夹抗。
異步:在另一條線程中執(zhí)行(不用等待當(dāng)前代碼執(zhí)行完绳慎,就能夠執(zhí)行下一條),不會阻塞當(dāng)前線程漠烧。
常見隊列:
為了方便 GCD 使用杏愤,蘋果默認(rèn)提供了主隊列和全局隊列。 我們不需要創(chuàng)建只需要獲取沽甥。
- 主隊列 (串行)
let mainQueue = DispatchQueue.main
- 全局隊列 (并發(fā))
let globalQueue = DispatchQueue.global()
全局隊列默認(rèn)是并發(fā)隊列声邦,在不進行第三方框架或者大型的商業(yè)應(yīng)用開發(fā),全局隊列基本夠用摆舟。
任務(wù)
需要執(zhí)行操作, 任務(wù)是使用閉包( oc: block) 封裝的代碼塊亥曹。
廢話到此完畢!
1. 項目開發(fā)中 GCD 代碼使用
print("DispatchQueue.main.sync: befor", Thread.current)
DispatchQueue.global().async {
print("DispatchQueue.global().async: Time task", Thread.current, "\n --: 耗時操作在后臺線程中執(zhí)行恨诱!")
DispatchQueue.main.async {
print("DispatchQueue.main.async: update UI", Thread.current, "\n --: 耗時操作執(zhí)行完畢后在主線程更新 UI 界面媳瞪!")
}
}
print("DispatchQueue.main.sync: after", Thread.current)
// 打印:
DispatchQueue.main.sync: befor <NSThread: 0x60800007abc0>{number = 1, name = main}
DispatchQueue.main.sync: after <NSThread: 0x60800007abc0>{number = 1, name = main}
DispatchQueue.global().async: Time task <NSThread: 0x6080002662c0>{number = 3, name = (null)}
--: 耗時操作在后臺線程中執(zhí)行照宝!
DispatchQueue.main.async: update UI <NSThread: 0x60800007abc0>{number = 1, name = main}
--: 耗時操作執(zhí)行完畢后在主線程更新 UI 界面蛇受!
/*
after 執(zhí)行的先后順序是不確定的。是由 GCD 決定厕鹃。
這里牽扯到一個概念: 線程間通訊兢仰! 說白的就是在線程間進行數(shù)據(jù)(信號)的傳遞乍丈。
*/
如果你只是單純的找 GCD 在 swift 中怎么使用,看到這里你基本可以關(guān)掉這篇博客把将,開心的寫代碼去了轻专。
2. GCD 使用 —— 精講
先來了解 GCD 在 Swift 中的變化
GCD 框架頭文件改變
import Dispatch.base // 沒有實質(zhì)性內(nèi)容
import Dispatch.block // 沒有實質(zhì)性內(nèi)容
import Dispatch.data // 沒有實質(zhì)性內(nèi)容
import Dispatch.group
import Dispatch.io
import Dispatch.object
import Dispatch.once // 沒有實質(zhì)性內(nèi)容
import Dispatch.queue
import Dispatch.semaphore
import Dispatch.source
import Dispatch.time
import Dispatch
import os_object
// 在 swift3.0 中新加的, OS_object 繼承自 NSObject
// 在 GCD 中所有的對象都間接的繼承自 NSObject察蹲。
import os_object
open class OS_object : NSObject {
}
Swift 中最大的變化其實就是更加的面相對象了,使用更加的方便簡潔洽议,擺脫了 OC 時代函數(shù)式的使用方式宗收。
GCD 使用先來個個人小的總結(jié):
口訣:同步不開異步開,串行開1條亚兄,并行開多條混稽。
來,跟著哥一起念儿捧。( 我怕你們打我荚坞,你們還是別念了,我解釋一下菲盾。)
同步不開異步開颓影,串行開1條,并行開多條懒鉴。
單純這么簡單的看是有誤解的诡挂, 在我的評論中就可以看到。
具體的意思是:
隊列中的任務(wù)同步執(zhí)行临谱,隊列就不具有開啟線程的能力璃俗, 隊列中的任務(wù)異步執(zhí)行,隊列就具有開啟線程的能力悉默。
(同步和異步執(zhí)行決定的是否有開啟線程的能力)
如果隊列具 **有開啟線程的能力 (隊列任務(wù)異步執(zhí)行) ** 且隊列是 串行隊列 瓣履,那么將會 開啟 1 條線程 愿棋。
如果隊列具 **有開啟線程的能力 (隊列任務(wù)異步執(zhí)行) ** 且隊列是 并發(fā)隊列 ,那么將會 開啟 多 條線程 。開啟線程的條數(shù)由 GCD 決定托慨。
** ( 串行和并發(fā)決定的是開幾條線程 ) **
** 如果真正理解了上面這些治拿,多 GCD 的使用和面試基本沒什么障礙定罢。 **
2.1 全局隊列
全局隊列是獲取的族购,不是程序員創(chuàng)建的。
為了方便 GCD 的使用抵拘,apple 默認(rèn)為我們提供的哎榴。
全局隊列默認(rèn)是并發(fā)隊列,在不是進行第三方框架或者大型的商業(yè)應(yīng)用開發(fā),全局隊列基本夠用尚蝌。
全局 ( 并發(fā) ) 隊列異步執(zhí)行 :
并發(fā)隊列異步(不阻塞當(dāng)前線程)執(zhí)行(隊列就具有開啟線程的能力)迎变, 隊列會開啟多條線程。
任務(wù)異步執(zhí)行不會阻塞當(dāng)前線程飘言,
befor 在最前氏豌,
after 在任意位置,
task 執(zhí)行順序不確定 —— 并發(fā)執(zhí)行(index可以確認(rèn))热凹。
task 并發(fā)執(zhí)行 —— 并發(fā)執(zhí)行(number可以確認(rèn))。
異步開線程 number 可以確定開啟了多條線程
開的線程數(shù)由 GCD 決定泪电。 可以看到線程的 number 有重復(fù)般妙,是 GCD 對線程進行了復(fù)用。
func async() {
print("DispatchQueue.global().async: befor", Thread.current)
// 全局隊列進行 10次異步
for index in 0..<10 {
DispatchQueue.global().async {
print("DispatchQueue.global().async: task:(taskIndex:\(index)", Thread.current)
}
}
print("DispatchQueue.global().async: after", Thread.current)
}
打酉嗨佟:
DispatchQueue.global().async: befor <NSThread: 0x60800006a8c0>{number = 1, name = main}
DispatchQueue.global().async: task:(taskIndex:1 <NSThread: 0x600000079780>{number = 3, name = (null)}
DispatchQueue.global().async: task:(taskIndex:2 <NSThread: 0x6000000797c0>{number = 4, name = (null)}
DispatchQueue.global().async: task:(taskIndex:0 <NSThread: 0x600000079880>{number = 5, name = (null)}
DispatchQueue.global().async: task:(taskIndex:3 <NSThread: 0x608000074e00>{number = 6, name = (null)}
DispatchQueue.global().async: task:(taskIndex:4 <NSThread: 0x600000079780>{number = 3, name = (null)}
DispatchQueue.global().async: task:(taskIndex:5 <NSThread: 0x6000000797c0>{number = 4, name = (null)}
DispatchQueue.global().async: after <NSThread: 0x60800006a8c0>{number = 1, name = main}
DispatchQueue.global().async: task:(taskIndex:6 <NSThread: 0x600000079880>{number = 5, name = (null)}
DispatchQueue.global().async: task:(taskIndex:7 <NSThread: 0x608000074e00>{number = 6, name = (null)}
DispatchQueue.global().async: task:(taskIndex:8 <NSThread: 0x600000079780>{number = 3, name = (null)}
DispatchQueue.global().async: task:(taskIndex:9 <NSThread: 0x6000000797c0>{number = 4, name = (null)}
全局 ( 并發(fā) ) 隊列同步執(zhí)行 :
并發(fā)隊列同步(阻塞當(dāng)前線程)執(zhí)行(隊列就不具有開啟線程的能力)碟渺, 隊列不會開啟線程(代碼都在主線程中執(zhí)行)。
任務(wù)同步執(zhí)行會阻塞當(dāng)前線程突诬,
befor 在最前苫拍,
after 在最后,
task 執(zhí)行順序確定 —— 阻塞旺隙。
同步?jīng)]有開啟線程 number 可以確定沒有開啟多條線程绒极。所有的代碼都在 主線程中執(zhí)行。
func sync() {
print("DispatchQueue.global().sync: befor", Thread.current)
for index in 0..<10 {
DispatchQueue.global().sync {
print("DispatchQueue.global().sync: task:(taskIndex:\(index))", Thread.current)
}
}
print("DispatchQueue.global().sync: after", Thread.current)
}
打邮呓荨:
DispatchQueue.global().sync: befor <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:0) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:1) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:2) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:3) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:4) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:5) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:6) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:7) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:8) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:9) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: after <NSThread: 0x60800007fa80>{number = 1, name = main}
2.2 主隊列
主隊列是獲取的垄提,不是程序員創(chuàng)建的,apple 默認(rèn)為我們提供的周拐。
(app 開發(fā)中铡俐,所有的 UI 更新操作都應(yīng)該在主線程中進行)
主隊列(串行)異步執(zhí)行
主隊列異步(不會阻塞當(dāng)前線程)執(zhí)行(隊列就具有開啟線程的能力), 隊列會開啟線程(開啟的線程就是主線程)妥粟。
> 有朋友問我审丘,異步會開啟線程, 主隊列異步就不會開啟線程勾给。
> 我當(dāng)時還信以為真滩报。認(rèn)為自己錯誤,說特殊情況特殊處理锦秒。 其實說白了就是學(xué)藝不精露泊。
> 由于主隊列是我們獲取的,不是我們創(chuàng)建的旅择,在某種意識中會認(rèn)為主線程不是在主隊列中創(chuàng)建的惭笑。(認(rèn)為一開始就存在的。)
> 任務(wù)異步執(zhí)行不會阻塞當(dāng)前線程,
befor 在最前沉噩,
after 在第二捺宗,
task 執(zhí)行順序確定 —— 串行執(zhí)行(index可以確認(rèn))。
同步?jīng)]有開啟線程 number 可以確定沒有開啟多條線程川蒙。所有的代碼都在 主線程中執(zhí)行蚜厉。
主隊列異步的操作主要用在更新 UI 操作中。 具體參考 項目開發(fā)中 GCD 代碼使用畜眨。
func async() {
print("DispatchQueue.main.async: befor", Thread.current)
for index in 0..<10 {
DispatchQueue.main.async {
print("DispatchQueue.main.async: task:(taskIndex:\(index)", Thread.current)
}
}
print("DispatchQueue.main.async: after", Thread.current)
}
打又缗!:
DispatchQueue.main.async: befor <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: after <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:0 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:1 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:2 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:3 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:4 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:5 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:6 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:7 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:8 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:9 <NSThread: 0x60800006ddc0>{number = 1, name = main}
主隊列(串行)同步執(zhí)行
執(zhí)行的效果就倆字 ** 死鎖**
主線程同步,在 Swift 中康聂,編譯階段就報錯贰健,在 oc 中是在運行的時候才能發(fā)現(xiàn)。體現(xiàn)的主要是界面的 “假死”恬汁。
2.3 自定義隊列
/*
label: 隊列名稱
qos: 服務(wù)質(zhì)量
// 后臺優(yōu)先級
public static let background: DispatchQoS
// 實用工具優(yōu)先級別(耗時操作伶椿,可以使用這個)
public static let utility: DispatchQoS
// 默認(rèn)優(yōu)先級(一般不是給程序員實用的,用來重置隊列用的)
public static let `default`: DispatchQoS
// 用戶期望優(yōu)先級(不要放太耗時的操作)
public static let userInitiated: DispatchQoS
// 用戶交互(希望盡快完成氓侧,用戶很希望得到結(jié)果脊另。個人覺得這個和主線的的線程優(yōu)先級是一樣的)
public static let userInteractive: DispatchQoS
// 未指定
public static let unspecified: DispatchQoS
attributes: 隊列屬性
// 并發(fā)
public static let concurrent: DispatchQueue.Attributes
// 初始化不活躍
public static let initiallyInactive: DispatchQueue.Attributes
autoreleaseFrequency: 自動釋放頻率
public enum AutoreleaseFrequency {
// 繼承
case inherit
// 工作項
case workItem
// 從來沒有,永遠不
case never
}
target: 目標(biāo)隊列
( 這些參數(shù)我也沒搞明白)
*/
public convenience init(label: String,
qos: DispatchQoS = default,
attributes: DispatchQueue.Attributes = default,
autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency = default,
target: DispatchQueue? = default)
在沒有搞明白參數(shù)的時候约巷,由于 swift 可以使用默認(rèn)參數(shù)偎痛, 我們可以使用默認(rèn)參數(shù)。
自定義(串行)隊列異步執(zhí)行
// 使用默認(rèn)的構(gòu)造函數(shù)創(chuàng)建了一個隊列(并不知隊列是串行還是并發(fā))
// api 文檔沒有給夠足夠的信息载庭。 后期的文檔描述完整后可以直接查看文檔看彼。
func async() {
print("DispatchQueue(label: \"laughing\").async: befor", Thread.current)
let queue = DispatchQueue(label: "laughing")
for index in 0..<10 {
queue.async {
print("DispatchQueue(label: \"laughing\").async: task:(taskIndex:\(index)", Thread.current)
}
}
print("DispatchQueue(label: \"laughing\").async: after", Thread.current)
}
/*
這么寫你會有一種串行隊列并發(fā)執(zhí)行的錯覺。
for index in 0..<10 {
DispatchQueue(label: "laughing").sync {
print("DispatchQueue(label: \"laughing\").sync: task:(taskIndex:\(index))", Thread.current)
}
}
*/
打忧艟邸:
DispatchQueue(label: "laughing").async: befor <NSThread: 0x608000067180>{number = 1, name = main}
DispatchQueue(label: "laughing").async: after <NSThread: 0x608000067180>{number = 1, name = main}
DispatchQueue(label: "laughing").async: task:(taskIndex:0 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:1 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:2 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:3 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:4 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:5 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:6 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:7 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:8 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:9 <NSThread: 0x608000074200>{number = 3, name = (null)}
** 由于只異步執(zhí)行只開了1 條線程靖榕, 可只。 默認(rèn)創(chuàng)建的隊列是 串行隊列**
自定義(串行)隊列同步執(zhí)行
串行隊列同步執(zhí)行顽铸,沒有開啟線程茁计。 代碼在主線程中執(zhí)行。
func sync() {
print("DispatchQueue(label: \"laughing\").sync: befor", Thread.current)
let queue = DispatchQueue(label: "laughing")
for index in 0..<10 {
queue.sync {
print("DispatchQueue(label: \"laughing\").sync: task:(taskIndex:\(index))", Thread.current)
}
}
/*
這么寫你會有一種串行隊列并發(fā)執(zhí)行的錯覺谓松。
for index in 0..<10 {
DispatchQueue(label: "laughing").sync {
print("DispatchQueue(label: \"laughing\").sync: task:(taskIndex:\(index))", Thread.current)
}
}
*/
print("DispatchQueue(label: \"laughing\").sync: after", Thread.current)
}
打有茄埂:
DispatchQueue(label: "laughing").sync: befor <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:0) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:1) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:2) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:3) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:4) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:5) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:6) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:7) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:8) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:9) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: after <NSThread: 0x600000071d40>{number = 1, name = main}
自定義(并發(fā))隊列異步執(zhí)行
(參考全局隊列)
func async1() {
print("DispatchQueue(label: \"laughing1\").async: befor", Thread.current)
let queue = DispatchQueue(label: "laughing1", attributes: DispatchQueue.Attributes.concurrent)
for index in 0..<10 {
queue.async {
print("DispatchQueue(label: \"laughing1\").async: task:(taskIndex:\(index)", Thread.current)
}
}
print("DispatchQueue(label: \"laughing1\").async: after", Thread.current)
}
打印
DispatchQueue(label: "laughing1").async: befor <NSThread: 0x600000261d80>{number = 1, name = main}
DispatchQueue(label: "laughing1").async: after <NSThread: 0x600000261d80>{number = 1, name = main}
DispatchQueue(label: "laughing1").async: task:(taskIndex:1 <NSThread: 0x60800026d380>{number = 3, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:3 <NSThread: 0x60800026d380>{number = 3, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:4 <NSThread: 0x60800026d380>{number = 3, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:2 <NSThread: 0x60800026d9c0>{number = 4, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:5 <NSThread: 0x60800026d380>{number = 3, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:7 <NSThread: 0x60800026d9c0>{number = 4, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:6 <NSThread: 0x60800026da00>{number = 5, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:0 <NSThread: 0x60800026db40>{number = 6, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:8 <NSThread: 0x60800026d380>{number = 3, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:9 <NSThread: 0x60800026d9c0>{number = 4, name = (null)}
自定義(并發(fā))隊列同步執(zhí)行
func sync1() {
print("DispatchQueue(label: \"laughing1\").sync: befor", Thread.current)
let queue = DispatchQueue(label: "laughing1", attributes: DispatchQueue.Attributes.concurrent)
for index in 0..<10 {
queue.sync {
print("DispatchQueue(label: \"laughing1\").sync: task:(taskIndex:\(index))", Thread.current)
}
}
/*
這么寫你會有一種串行隊列并發(fā)執(zhí)行的錯覺。
for index in 0..<10 {
DispatchQueue(label: "laughing").sync {
print("DispatchQueue(label: \"laughing\").sync: task:(taskIndex:\(index))", Thread.current)
}
}
*/
print("DispatchQueue(label: \"laughing1\").sync: after", Thread.current)
}
打印
DispatchQueue(label: "laughing1").sync: befor <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:0) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:1) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:2) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:3) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:4) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:5) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:6) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:7) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:8) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:9) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: after <NSThread: 0x608000061cc0>{number = 1, name = main}