轉自:http://blog.csdn.net/zhangao0086/article/details/38904923 Bannings的專欄
Grand Central Dispatch(GCD)是異步執行任務的技術之一。一般將應用程序中記述的線程管理用的代碼在系統級中實現。開發者只需要定義想執行的任務並追加到適當的Dispatch Queue中,GCD就能生成必要的線程並計劃執行任務。由於線程管理是作爲系統的一部分來實現的,因此可統一管理,也可執行任務,這樣就比以前的線程更有效率。
Dispatch Queue
Dispatch Queue是用來執行任務的隊列,是GCD中最基本的元素之一。
Dispatch Queue分爲兩種:
- Serial Dispatch Queue,按添加進隊列的順序(先進先出)一個接一個的執行
- Concurrent Dispatch Queue,併發執行隊列裏的任務
let myQueue: dispatch_queue_t = dispatch_queue_create("com.xxx", nil)
第一個參數是隊列的名稱,一般是使用倒序的全域名。雖然可以不給隊列指定一個名稱,但是有名稱的隊列可以讓我們在遇到問題時更好調試;當第二個參數爲nil時返回Serial Dispatch Queue,如上面那個例子,當指定爲DISPATCH_QUEUE_CONCURRENT時返回Concurrent Dispatch Queue。
需要注意一點,如果是在OS X 10.8或iOS 6以及之後版本中使用,Dispatch Queue將會由ARC自動管理,如果是在此之前的版本,需要自己手動釋放,如下:
let myQueue: dispatch_queue_t = dispatch_queue_create("com.xxx", nil)
dispatch_async(myQueue, { () -> Void in
println("in Block")
})
dispatch_release(myQueue)
以上是通過手動創建的方式來獲取Dispatch Queue,第二種方式是直接獲取系統提供的Dispatch Queue。
要獲取的Dispatch Queue無非就是兩種類型:
- Main Dispatch Queue
- Global Dispatch Queue / Concurrent Dispatch Queue
//獲取Main Dispatch Queue
let mainQueue = dispatch_get_main_queue()
//獲取Global Dispatch Queue
let globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_after
dispatch_after能讓我們添加進隊列的任務延時執行,比如想讓一個Block在10秒後執行:
var time = dispatch_time(DISPATCH_TIME_NOW, (Int64)(10 * NSEC_PER_SEC))
dispatch_after(time, globalQueue) { () -> Void in
println("在10秒後執行")
}
NSEC_PER_SEC表示的是秒數,它還提供了NSEC_PER_MSEC表示毫秒。
獲取一個dispatch_time_t類型的值可以通過兩種方式來獲取,以上是第一種方式,即通過dispatch_time函數,另一種是通過dispatch_walltime函數來獲取,dispatch_walltime需要使用一個timespec的結構體來得到dispatch_time_t。通常dispatch_time用於計算相對時間,dispatch_walltime用於計算絕對時間,我寫了一個把NSDate轉成dispatch_time_t的Swift方法:
func getDispatchTimeByDate(date: NSDate) -> dispatch_time_t {
let interval = date.timeIntervalSince1970
var second = 0.0
let subsecond = modf(interval, &second)
var time = timespec(tv_sec: __darwin_time_t(second), tv_nsec: (Int)(subsecond * (Double)(NSEC_PER_SEC)))
return dispatch_walltime(&time, 0)
}
這個方法接收一個NSDate對象,然後把NSDate轉成dispatch_walltime需要的timespec結構體,最後再把dispatch_time_t返回,同樣是在10秒後執行,之前的代碼在調用部分需要修改成:
var time = getDispatchTimeByDate(NSDate(timeIntervalSinceNow: 10))
dispatch_after(time, globalQueue) { () -> Void in
println("在10秒後執行")
}
dispatch_group
let globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
let group = dispatch_group_create()
dispatch_group_async(group, globalQueue) { () -> Void in
println("1")
}
dispatch_group_async(group, globalQueue) { () -> Void in
println("2")
}
dispatch_group_async(group, globalQueue) { () -> Void in
println("3")
}
dispatch_group_notify(group, globalQueue) { () -> Void in
println("completed")
}
let globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
let group = dispatch_group_create()
dispatch_group_async(group, globalQueue) { () -> Void in
println("1")
}
dispatch_group_async(group, globalQueue) { () -> Void in
println("2")
}
dispatch_group_async(group, globalQueue) { () -> Void in
println("3")
}
//使用dispatch_group_wait函數
dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
println("completed")
dispatch_barrier_async
dispatch_barrier_async就如同它的名字一樣,在隊列執行的任務中增加“柵欄”,在增加“柵欄”之前已經開始執行的block將會繼續執行,當dispatch_barrier_async開始執行的時候其他的block處於等待狀態,dispatch_barrier_async的任務執行完後,其後的block纔會執行。我們簡單的寫個例子,假設這個例子有讀文件和寫文件的部分:
func writeFile() {
NSUserDefaults.standardUserDefaults().setInteger(7, forKey: "Integer_Key")
}
func readFile(){
print(NSUserDefaults.standardUserDefaults().integerForKey("Integer_Key"))
}
NSUserDefaults.standardUserDefaults().setInteger(9, forKey: "Integer_Key")
let globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(globalQueue) {self.readFile()}
dispatch_async(globalQueue) {self.readFile()}
dispatch_async(globalQueue) {self.readFile()}
dispatch_async(globalQueue) {self.readFile()}
dispatch_barrier_async(globalQueue) {self.writeFile() ; self.readFile()}
dispatch_async(globalQueue) {self.readFile()}
dispatch_async(globalQueue) {self.readFile()}
dispatch_async(globalQueue) {self.readFile()}
dispatch_apply
let globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_apply(10, globalQueue) { (index) -> Void in
print(index)
}
print("completed")
let globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(globalQueue, { () -> Void in
dispatch_apply(10, globalQueue) { (index) -> Void in
print(index)
}
print("completed")
})
print("在dispatch_apply之前")
dispatch_suspend / dispatch_resume
//暫停
dispatch_suspend(globalQueue)
//恢復
dispatch_resume(globalQueue)
Dispatch Semaphore
let globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
let semaphore = dispatch_semaphore_create(1)
for i in 0 ... 9 {
dispatch_async(globalQueue, { () -> Void in
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
let time = dispatch_time(DISPATCH_TIME_NOW, (Int64)(2 * NSEC_PER_SEC))
dispatch_after(time, globalQueue) { () -> Void in
print("2秒後執行")
dispatch_semaphore_signal(semaphore)
}
})
}
dispatch_once
class SingletonObject {
class var sharedInstance : SingletonObject {
struct Static {
static var onceToken : dispatch_once_t = 0
static var instance : SingletonObject? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = SingletonObject()
}
return Static.instance!
}
}