一個(gè)常見(jiàn)的場(chǎng)景就是在一個(gè)全局隊(duì)列進(jìn)行一些操作后切換到主線程配置UI。現(xiàn)在是這么寫(xiě):
DispatchQueue.global().async {
// code
DispatchQueue.main.async {
// 主線程中
}
}
概念:
串行 VS 并發(fā)
串行與并發(fā)用來(lái)表述隊(duì)列里面的任務(wù)執(zhí)行的順序啄刹。 串行(serial) 在同一時(shí)間點(diǎn)總是單獨(dú)執(zhí)行一個(gè)任務(wù)乙墙,并發(fā)(concurrent)則可以同時(shí)執(zhí)行多個(gè)任務(wù)颠锉。
任務(wù)
任務(wù)可以看成是一段未被執(zhí)行的代碼塊, 一個(gè)方法可以是一個(gè)一個(gè)任務(wù), 一寫(xiě)代碼的集合可以看做是一個(gè)任務(wù), 在GCD中, 隊(duì)列里面的任務(wù)就是未被執(zhí)行的一塊閉包
同步 VS 異步
同步和異步表述的是函數(shù)何時(shí)將控制權(quán)返回給調(diào)用者拼卵,以及在返回時(shí)任務(wù)的完成情況。
同步(任務(wù)一個(gè)一個(gè)執(zhí)行)函數(shù)只有在任務(wù)完成后才會(huì)返回虏杰。
異步(任務(wù)可以并發(fā)執(zhí)行)函數(shù)會(huì)立即返回讥蟆,不會(huì)等待任務(wù)完成。因此異步函數(shù)不會(huì)阻塞當(dāng)前線程纺阔。
主隊(duì)列
系統(tǒng)提供了一種特殊的順序隊(duì)列 main queue瘸彤。和其他的順序隊(duì)列一樣,在這個(gè)隊(duì)列里的任務(wù)同一時(shí)刻只有一個(gè)在執(zhí)行笛钝。然而质况,這個(gè)隊(duì)列保證了所有任務(wù)會(huì)在主線程中執(zhí)行,主線程是唯一一個(gè)允許更新UI的線程玻靡。這個(gè)隊(duì)列用來(lái)向 UIView 對(duì)象發(fā)消息或發(fā)通知结榄。
隊(duì)列優(yōu)先級(jí)
原先的GCD只有四個(gè)優(yōu)先級(jí),high囤捻,default潭陪,low,background
然而現(xiàn)在的GCD有六個(gè)優(yōu)先級(jí)最蕾,background,utility老厌,default瘟则,userInitiated,userInteractive枝秤,unspecified
這些優(yōu)先級(jí)有結(jié)構(gòu)體DispatchQoS來(lái)管理
串行隊(duì)列
//創(chuàng)建的隊(duì)列默認(rèn)是串行的, 隊(duì)列里的任務(wù)是以此按照添加的順序來(lái)執(zhí)行的(FIFO)
//第一個(gè)for循環(huán)結(jié)束之后才會(huì)執(zhí)行下一個(gè)for循環(huán)
func serialQueues() {
let queue = DispatchQueue(label: "com.jason")
//創(chuàng)建一個(gè)含有優(yōu)先級(jí)的串行隊(duì)列
//let anotherQueue = DispatchQueue(label:"com.appcoda.anotherQueue", qos:.utility)
queue.async {
for i in 1..<10 {
print("??" + String(i))
}
}
queue.async {
for i in 1..<10 {
print("??" + String(i))
}
}
}
并行隊(duì)列
func concurrentQueues() {
//并行隊(duì)列, 隊(duì)列里面的任務(wù)并發(fā)執(zhí)行
/**
label: 隊(duì)列的唯一標(biāo)識(shí)符
qos: 優(yōu)先級(jí)
attributes: 隊(duì)列類(lèi)型
*/
let anotherQueue = DispatchQueue(label:"com.appcoda.anotherQueue", qos:.utility, attributes:.concurrent)
anotherQueue.async {
for i in 1..<10 {
print("??" + String(i))
}
}
anotherQueue.async {
for i in 1..<10 {
print("??" + String(i))
}
}
}
初始化不活躍的串行隊(duì)列
var inactiveQueue: DispatchQueue!
func concurrentQueues() {
//串行隊(duì)列, 初始不活躍, 需要時(shí)才執(zhí)行
let anotherQueue = DispatchQueue(label:"com.appcoda.anotherQueue", qos:.utility, attributes:.initiallyInactive)
inactiveQueue = anotherQueue
anotherQueue.async {
for i in 1..<10 {
print("??" + String(i))
}
}
anotherQueue.async {
for i in 1..<10 {
print("??" + String(i))
}
}
}
調(diào)用
concurrentQueues()
if let queue = inactiveQueue {
queue.activate()
}
初始化不活躍的并行隊(duì)列
//并行隊(duì)列, 初始不活躍
let anotherQueue = DispatchQueue(label:"com.appcoda.anotherQueue", qos:.utility, attributes:[.initiallyInactive, .concurrent])
延遲執(zhí)行
func queueWithDelay() {
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
print("延遲5秒執(zhí)行")
}
}
DispatchWorkItem
DispatchWorkItem是一個(gè)代碼塊醋拧,它可以被分到任何的隊(duì)列,包含的代碼可以在后臺(tái)或主線程中被執(zhí)行淀弹,簡(jiǎn)單來(lái)說(shuō):它被用于替換我們前面寫(xiě)的閉包
func useWorkItem() {
var value = 10
//創(chuàng)建一個(gè)workItem
let workItem = DispatchWorkItem {
value += 5
}
//激活workItem
workItem.perform()
//獲取全局一個(gè)隊(duì)列
let queue = DispatchQueue.global()
//在隊(duì)列里面執(zhí)行workItem
queue.async(execute: workItem)
//workItem被執(zhí)行完成后收到的通知
workItem.notify(queue: DispatchQueue.main) {
print(value)
}
}
DispatchGroup(任務(wù)組)
如果想在dispatch_queue中所有的任務(wù)執(zhí)行完成后再做某種操作可以使用DispatchGroup丹壕。原先的dispatch_group_t由現(xiàn)在的DispatchGroup對(duì)象代替。
let group = DispatchGroup()
let queueBook = DispatchQueue(label: "book")
queueBook.async(group: group) {
// 下載圖書(shū)
}
let queueVideo = DispatchQueue(label: "video")
queueVideo.async(group: group) {
// 下載視頻
}
group.notify(queue: DispatchQueue.main) {
// 下載完成
}
DispatchGroup會(huì)在組里的操作都完成后執(zhí)行notify薇溃。
監(jiān)聽(tīng) group 中任務(wù)的完成狀態(tài)菌赖,當(dāng)所有的任務(wù)都執(zhí)行完成后,追加任務(wù)到 group 中沐序,并執(zhí)行任務(wù)琉用。
func groupNotify() {
let group = DispatchGroup();
let mainQueue = DispatchQueue.main;
let queue = DispatchQueue.global();
let item1 = DispatchWorkItem.init {
for _ in 0..<2 {
Thread.sleep(forTimeInterval: 2)
print("1---\(Thread.current)")
}
}
let item2 = DispatchWorkItem.init {
for _ in 0..<2 {
Thread.sleep(forTimeInterval: 2)
print("2---\(Thread.current)")
}
}
queue.async(group: group, execute: item1)
queue.async(group: group, execute: item2)
group.notify(queue: mainQueue) {
for _ in 0..<2 {
Thread.sleep(forTimeInterval: 2)
print("3---\(Thread.current)")
}
}
}
dispatch_group_enter堕绩、dispatch_group_leave
dispatch_group_enter 標(biāo)志著一個(gè)任務(wù)追加到 group,執(zhí)行一次邑时,相當(dāng)于 group 中未執(zhí)行完畢任務(wù)數(shù)+1
dispatch_group_leave 標(biāo)志著一個(gè)任務(wù)離開(kāi)了 group奴紧,執(zhí)行一次,相當(dāng)于 group 中未執(zhí)行完畢任務(wù)數(shù)-1晶丘。
當(dāng) group 中未執(zhí)行完畢任務(wù)數(shù)為0的時(shí)候黍氮,才會(huì)使dispatch_group_wait解除阻塞,以及執(zhí)行追加到dispatch_group_notify中的任務(wù)浅浮。
這里的dispatch_group_enter沫浆、dispatch_group_leave組合,其實(shí)等同于dispatch_group_async脑题。
func groupEnterAndLeave() {
let group = DispatchGroup();
let mainQueue = DispatchQueue.main;
let queue = DispatchQueue.global();
group.enter()
queue.async {
for _ in 0..<2 {
Thread.sleep(forTimeInterval: 2)
print("1---\(Thread.current)")
}
group.leave()
}
group.enter()
queue.async {
for _ in 0..<2 {
Thread.sleep(forTimeInterval: 2)
print("2---\(Thread.current)")
}
group.leave()
}
group.notify(queue: mainQueue) {
for _ in 0..<2 {
Thread.sleep(forTimeInterval: 2)
print("3---\(Thread.current)")
}
}
}
單例
//final關(guān)鍵字的作用是這個(gè)類(lèi)或方法不希望被繼承和重寫(xiě)
final class Single: NSObject {
static let shared = Single()
//這里的所有單例init方法一定要定義成private的件缸,不然外部依然可以使用init方法初始化變量。
private override init() {}
}
//靜態(tài)變量進(jìn)行創(chuàng)建
final class Singleton {
static private let staticInstance: Singleton = Singleton()
static func sharedInstance() -> Singleton {
return staticInstance
}
private init() {}
}