什么是GCD?
全稱Grand Center Dispatch,是純C語言的,提供了非常強大的函數,是蘋果公司為了解決多核的并行運算而推出的。
優點:
1.自動利用更多的CPU內核
2.自動管理線程的生命周期
3.使用簡單(確定想要做的事情(任務),然后添加到隊列,按照指定的同步、異步方式執行,CGD會自動將隊列中的任務取出放到對應的線程中執行,任務的取出遵循FIFO原則,先進先出)
核心概念:
1.任務:需要執行的事情
2.隊列:存放任務的集合
基礎用法
隊列、函數知識點
串行隊列:一個接一個的調度任務
并發隊列:可以同時調度多個任務
主隊列:全局串行隊列,由主線程串行調度任務,并且只有一個
全局隊列:沒有名稱的并發隊列
同步執行(sync):當前指令不完成,就不會執行下一條指令,不會開啟新線程
異步執行(async):當前指令不完成,同樣可以執行下一條指令,會開啟新線程
注意點:
主隊列
+ 同步執行
會產生死鎖
創建隊列
/// 創建串行隊列
// OC
- (void)creatSerialQueue {
/**
label: 隊列標識
dispatch_queue_attr_t: 隊列屬性,DISPATCH_QUEUE_SERIAL串行,DISPATCH_QUEUE_CONCURRENT并行
*/
dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
NSLog(@"任務1");
// 睡3秒
[NSThread sleepForTimeInterval:3.0];
});
dispatch_async(serialQueue, ^{
NSLog(@"任務2");
});
dispatch_async(serialQueue, ^{
NSLog(@"任務3");
});
}
// Swift
func creatSerialtQueue() -> () {
// 默認初始化方法創建的就是一個串行隊列
let serialQueue = DispatchQueue(label: "serialQueue")
serialQueue.async {
print("任務1")
// 睡3秒
sleep(3)
}
serialQueue.async {
print("任務2")
}
serialQueue.async {
print("任務3")
}
}
雖然有sleep 3秒但是依然會等待、按順序執行
2017-04-03 11:04:21.441 OC-GCD測試[1943:158578] 任務1
2017-04-03 11:04:24.446 OC-GCD測試[1943:158578] 任務2
2017-04-03 11:04:24.446 OC-GCD測試[1943:158578] 任務3
/// 創建并行隊列
// OC
- (void)creatConcurrentQueue {
dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
NSLog(@"任務1");
// 睡3秒
[NSThread sleepForTimeInterval:3.0];
});
dispatch_async(concurrentQueue, ^{
NSLog(@"任務2");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"任務3");
});
}
// Swift
func creatConcurrentQueue() -> () {
// 創建并發的隊列,在attributes中聲明concurrent
let concurrentQueue = DispatchQueue(label: "concurrentQueue", attributes: DispatchQueue.Attributes.concurrent)
concurrentQueue.async {
print("任務1")
// 睡3秒
sleep(3)
}
concurrentQueue.async {
print("任務2")
}
concurrentQueue.async {
print("任務3")
}
}
sleep 3秒不會等待、并發執行
2017-04-03 11:01:26.550 OC-GCD測試[1897:154504] 任務2
2017-04-03 11:01:26.550 OC-GCD測試[1897:154507] 任務1
2017-04-03 11:01:26.550 OC-GCD測試[1897:154505] 任務3
同步執行(不會開啟線程)
// OC
- (void)synTest {
// 獲取一個全局隊列
dispatch_queue_t queque = dispatch_get_global_queue(0, 0);
// 創建一個任務
void(^task)() = ^() {
NSLog(@"當前線程:%@", [NSThread currentThread]);
};
// 執行任務
dispatch_sync(queque, task);
}
// Swift
func synTest() -> () {
// 獲取一個全局隊列
let queue = DispatchQueue.global()
// 創建一個任務
let task = {
print("當前線程:\(Thread.current)")
}
// 執行任務
queue.sync(execute: task)
}
控制臺輸出結果(同步不具備開啟線程的能力,在當前線程(主線程)執行,所以輸出number = 1, name = main
<NSThread: 0x6000000770c0>{number = 1, name = main}
異步執行(會開啟新的線程)
// OC
- (void)asynTest {
// 獲取一個全局隊列
dispatch_queue_t queque = dispatch_get_global_queue(0, 0);
// 創建一個任務
void(^task)() = ^() {
NSLog(@"當前線程:%@", [NSThread currentThread]);
};
// 執行任務
dispatch_async(queque, task);
}
// Swift
func asynTest() -> () {
// 獲取一個全局隊列
let queue = DispatchQueue.global()
// 創建一個任務
let task = {
print("當前線程:\(Thread.current)")
}
// 執行任務
queue.async(execute: task)
}
控制臺輸出結果(異步會開啟新的線程的,所以輸出number = 3, name = (null)
<NSThread: 0x608000267440>{number = 3, name = (null)}
異步拉回主線程
// OC
- (void)mainQueueTest {
// 獲取全局隊列
dispatch_queue_t globalQueueue = dispatch_get_global_queue(0, 0);
dispatch_async(globalQueueue, ^{
NSLog(@"異步執行操作");
[NSThread sleepForTimeInterval:3];
// 獲取主隊列
dispatch_queue_t mainQueueue = dispatch_get_main_queue();
dispatch_async(mainQueueue, ^{
NSLog(@"拉回主線程更新UI");
});
});
}
// Swift
func mainQueueTest() -> () {
DispatchQueue.global().async {
print("異步執行操作")
sleep(3)
DispatchQueue.main.async {
print("拉回主線程更新UI")
}
}
}