swift 3中對C層級的GCD的API進(jìn)行了徹頭徹尾的改變巴比。本文將從實(shí)際使用場景來了解一下新的api使用躬窜。
dispatch_async
一個(gè)常見的場景就是在一個(gè)全局隊(duì)列進(jìn)行一些操作后切換到主線程配置UI★啵現(xiàn)在是這么寫:
DispatchQueue.global().async?{
//?code
DispatchQueue.main.async?{
//?主線程中
}
}
global()是一個(gè)有著默認(rèn)參數(shù)的靜態(tài)函數(shù):
class?DispatchQueue?:?DispatchObject?{
public??class?var?main:?DispatchQueue
public?class?func?global(qos:?DispatchQoS.QoSClass?=?default)?->?DispatchQueue
}
sync
如果想同步執(zhí)行操作抬探,和async類似贵白,調(diào)用sync就可以了:
DispatchQueue.global().sync?{
//?同步執(zhí)行
}
優(yōu)先級:DispatchQoS
我們知道马澈,GCD 的默認(rèn)隊(duì)列優(yōu)先級有四個(gè):
DISPATCH_QUEUE_PRIORITY_HIGH
DISPATCH_QUEUE_PRIORITY_DEFAULT
DISPATCH_QUEUE_PRIORITY_LOW
DISPATCH_QUEUE_PRIORITY_BACKGROUND
現(xiàn)在則改為了QoSClass枚舉
public?enum?QoSClass?{
case?background
case?utility
case?`default`
case?userInitiated
case?userInteractive
case?unspecified
public?init?(rawValue:?qos_class_t)
public?var?rawValue:?qos_class_t?{?get?}
}
這些命名比原先的更加友好,能更好表達(dá)這個(gè)操作的意圖窟坐。
和原有的對應(yīng)關(guān)系是:
*?DISPATCH_QUEUE_PRIORITY_HIGH:?????????.userInitiated
*?DISPATCH_QUEUE_PRIORITY_DEFAULT:??????.default
*?DISPATCH_QUEUE_PRIORITY_LOW:??????????.utility
*?DISPATCH_QUEUE_PRIORITY_BACKGROUND:???.background
創(chuàng)建隊(duì)列
DispatchQueue的默認(rèn)初始化方法創(chuàng)建的就是一個(gè)同步隊(duì)列海渊,如果要?jiǎng)?chuàng)建并發(fā)的隊(duì)列,在attributes中聲明concurrent哲鸳。
//?同步隊(duì)列
let?serialQueue?=?DispatchQueue(label:?"queuename")
//?并發(fā)隊(duì)列
let?concurrentQueue?=?DispatchQueue(label:?"queuename",?attributes:?.concurrent)
推遲時(shí)間后執(zhí)行
原先的dispatch_time_t現(xiàn)在由DispatchTime對象表示臣疑。可以用靜態(tài)方法now獲得當(dāng)前時(shí)間徙菠,然后再通過加上一個(gè)DispatchTimeInterval枚舉來獲得一個(gè)需要延遲的時(shí)間讯沈。
let?delay?=?DispatchTime.now()?+?DispatchTimeInterval.seconds(60)DispatchQueue.main.asyncAfter(deadline:?delay)?{
//?延遲執(zhí)行}
這里也可以直接加上一個(gè)秒數(shù)。
let?three?=?DispatchTime.now()?+?3.0
因?yàn)镈ispatchTime中自定義了+號婿奔。
public?func?+(time:?DispatchTime,?seconds:?Double)?->?DispatchTime
DispatchGroup
如果想在dispatch_queue中所有的任務(wù)執(zhí)行完成后再做某種操作可以使用DispatchGroup缺狠。原先的dispatch_group_t由現(xiàn)在的DispatchGroup對象代替。
let?group?=?DispatchGroup()
let?queueBook?=?DispatchQueue(label:?"book")
queueBook.async(group:?group)?{
//?下載圖書
}
let?queueVideo?=?DispatchQueue(label:?"video")
queueVideo.async(group:?group)?{
//?下載視頻
}
group.notify(queue:?DispatchQueue.main)?{
//?下載完成
}
DispatchGroup會在組里的操作都完成后執(zhí)行notify萍摊。
如果有多個(gè)并發(fā)隊(duì)列在一個(gè)組里挤茄,我們想在這些操作執(zhí)行完了再繼續(xù),調(diào)用wait
group.wait()
DispatchWorkItem
使用DispatchWorkItem代替原來的dispatch_block_t冰木。
在DispatchQueue執(zhí)行操作除了直接傳了一個(gè)() -> Void類型的閉包外穷劈,還可以傳入一個(gè)DispatchWorkItem笼恰。
public?func?sync(execute?workItem:?DispatchWorkItem)
public?func?async(execute?workItem:?DispatchWorkItem)
DispatchWorkItem的初始化方法可以配置Qos和DispatchWorkItemFlags,但是這兩個(gè)參數(shù)都有默認(rèn)參數(shù)歇终,所以也可以只傳入一個(gè)閉包社证。
public?init(qos:?DispatchQoS?=?default,?flags:?DispatchWorkItemFlags?=?default,?block:?@escaping?@convention(block)?()?->?())
let?workItem?=?DispatchWorkItem?{
//?TODO:
}
DispatchWorkItemFlags枚舉中assignCurrentContext表示QoS根據(jù)創(chuàng)建時(shí)的context決定。
值得一提的是DispatchWorkItem也有wait方法练湿,使用方式和group一樣猴仑。調(diào)用會等待這個(gè)workItem執(zhí)行完。
let?myQueue?=?DispatchQueue(label:?"my.queue",?attributes:?.concurrent)
let?workItem?=?DispatchWorkItem?{
sleep(1)
print("done")
}
myQueue.async(execute:?workItem)
print("before?waiting")
workItem.wait()
print("after?waiting")
barrier
假設(shè)我們有一個(gè)并發(fā)的隊(duì)列用來讀寫一個(gè)數(shù)據(jù)對象肥哎。如果這個(gè)隊(duì)列里的操作是讀的辽俗,那么可以多個(gè)同時(shí)進(jìn)行。如果有寫的操作篡诽,則必須保證在執(zhí)行寫入操作時(shí)崖飘,不會有讀取操作在執(zhí)行,必須等待寫入完成后才能讀取杈女,否則就可能會出現(xiàn)讀到的數(shù)據(jù)不對朱浴。在之前我們用dipatch_barrier實(shí)現(xiàn)。
現(xiàn)在屬性放在了DispatchWorkItemFlags里达椰。
let?wirte?=?DispatchWorkItem(flags:?.barrier)?{
//?write?data}let?dataQueue?=?DispatchQueue(label:?"data",?attributes:?.concurrent)
dataQueue.async(execute:?wirte)
信號量
為了線程安全的統(tǒng)計(jì)數(shù)量翰蠢,我們會使用信號量作計(jì)數(shù)。原來的dispatch_semaphore_t現(xiàn)在用DispatchSemaphore對象表示啰劲。
初始化方法只有一個(gè)梁沧,傳入一個(gè)Int類型的數(shù)。
let?semaphore?=?DispatchSemaphore(value:?5)
//?信號量減一
semaphore.wait()
//信號量加一
semaphore.signal()
dispatch_once被廢棄
在swift 3中已經(jīng)被廢棄了蝇裤。
簡單的建議就是一些初始化場景就用懶加載吧廷支。
//?Examples?of?dispatch_once?replacements?with?global?or?static?constants?and?variables.
//?In?all?three,?the?initialiser?is?called?only?once.
//?Static?properties?(useful?for?singletons).
class?Object?{
static?let?sharedInstance?=?Object()
}
//?Global?constant.
let?constant?=?Object()
//?Global?variable.
var?variable:?Object?=?{
let?variable?=?Object()
variable.doSomething()
return?variable
}()