1.
什麼是GCD
全稱Grand Central Dispatch,可譯爲“中樞調度器”,純C語言,提供了非常多強大的函數
優點:
GCD會自動管理線程的生命週期(創建線程,調度任務,銷燬線程),
自動利用更多的CPU內核(比如雙核,四核)
GCD的任務的取出遵循隊列的FIFO原則:先進先出,後進後出
容易混淆的術語
1>.同步和異步主要影響:能不能開啓新的線程
同步:在當前線程中執行任務,不具備開啓新線程的能力
異步:在新的線程中執行任務,具備開啓新線程的能力
2>.併發和串行主要影響:任務的執行方式
併發:多個任務併發(同時)執行
併發:多個任務併發(同時)執行
串行:一個任務執行完畢後,再執行下一個任務
GCD中有2個用來執行任務的函數
2.執行的任務:
1>.用同步的方式執行任務
void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
queue:隊列
block:任務
2>.用異步的方式執行任務
void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
queue:隊列
block:任務
2>.用異步的方式執行任務
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
隊列的類型
GCD的隊列可以分爲2大類型
併發隊列(Concurrent Dispatch Queue)
可以讓多個任務併發(同時)執行(自動開啓多個線程同時執行任務)
GCD的隊列可以分爲2大類型
併發隊列(Concurrent Dispatch Queue)
可以讓多個任務併發(同時)執行(自動開啓多個線程同時執行任務)
併發功能只有在異步(dispatch_async)函數下才有效
串行隊列(Serial Dispatch Queue)
讓任務一個接着一個地執行(一個任務執行完畢後,再執行下一個任務)
讓任務一個接着一個地執行(一個任務執行完畢後,再執行下一個任務)
併發隊列 /**** 重要 *****/
GCD默認已經提供了全局的併發隊列,供整個應用使用,不需要手動創建
使用
dispatch_queue_t dispatch_get_global_queue(long identifier, unsigned long flags);
返回值 dispatch_queue_t 隊列
參數 long identifier 全局併發隊列優先級
使用
dispatch_queue_t dispatch_get_global_queue(long identifier, unsigned long flags);
返回值 dispatch_queue_t 隊列
參數 long identifier 全局併發隊列優先級
參數
unsigned long flags=0 此參數暫時無用,用0即可
//全局併發隊列的優先級
#define DISPATCH_QUEUE_PRIORITY_HIGH 2 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 默認(中)
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) 低
#define DISPATCH_QUEUE_PRIORITY_HIGH 2 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 默認(中)
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) 低
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
後臺
線程間的使用:
//異步併發執行:
3.
GCD
延遲執行
例如:
- (void)touchesBegan:(NSSet<UITouch
*> *)touches withEvent:(UIEvent
*)event
{
NSLog(@"----touchesBegan");
#if 0
//錯誤的做法 缺點:卡住當前線程
[NSThread sleepForTimeInterval:3];
NSLog(@"---下載圖片");
NSLog(@"----downloadfinished");
#endif
{
NSLog(@"----touchesBegan");
#if 0
//錯誤的做法 缺點:卡住當前線程
[NSThread sleepForTimeInterval:3];
NSLog(@"---下載圖片");
NSLog(@"----downloadfinished");
#endif
#if
0
2>
1.調用NSObject的方法
//一旦定製好
延遲任務後
不會卡住當前線程, 3秒後回到主線程中執行download方法不會卡住當前線程
[self
performSelector:@selector(download) withObject:nil
afterDelay:3.0f];
NSLog(@"----downloadfinished");
#endif
NSLog(@"----downloadfinished");
#endif
#if
0
//3秒後回到主線程中執行block中的代碼,不會造成卡頓
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"----下載圖片 %@",[NSThread currentThread]);
});
NSLog(@"----downloadfinished");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"----下載圖片 %@",[NSThread currentThread]);
});
NSLog(@"----downloadfinished");
#endif
//3秒後在新建的子線程中執行block中的代碼,不會造成卡頓
dispatch_queue_t
queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"----下載圖片 %@",[NSThread currentThread]);
});
NSLog(@"----downloadfinished");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"----下載圖片 %@",[NSThread currentThread]);
});
NSLog(@"----downloadfinished");
}
- (void)download
{
NSLog(@"---下載圖片 %@",[NSThread currentThread]);
{
NSLog(@"---下載圖片 %@",[NSThread currentThread]);
}
4.一次性代碼
- (void)download
{
//一次性代碼 使用dispatch_once_t函數能保證某段代碼在程序運行過程中只被執行1次(block中的代碼默認是線程安全的)
//永遠只執行一次,從函數的開始到結束
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"下載圖片");
});
// if (self.hasExcuted) return;
// NSLog(@"下載圖片");
// self.hasExcuted = YES;
{
//一次性代碼 使用dispatch_once_t函數能保證某段代碼在程序運行過程中只被執行1次(block中的代碼默認是線程安全的)
//永遠只執行一次,從函數的開始到結束
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"下載圖片");
});
// if (self.hasExcuted) return;
// NSLog(@"下載圖片");
// self.hasExcuted = YES;
}
五:
GCD
隊列組:
1.隊列組可以解決如下需求
首先:分別異步執行2個耗時操作
其次:等2個異步操作都執行完畢後,再回到主線程執行操作
//1.隊列組
dispatch_group_t group = dispatch_group_create();
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0);
dispatch_group_async(<#dispatch_group_t group#>, <#dispatch_queue_t queue#>, ^{
//下載圖片等操作
});
//(保證組裏面所有的任務都執行完成後 再執行notify函數裏面的block)
dispatch_group_notify(<#dispatch_group_t group#>, <#dispatch_queue_t queue#>, ^{
//執行圖片合併等操作
……..
//回到主線程顯示
dispatch_async(dispatch_get_main_queue(), ^{
//顯示內容等操作
});
});
//下載圖片等操作
});
//(保證組裏面所有的任務都執行完成後 再執行notify函數裏面的block)
dispatch_group_notify(<#dispatch_group_t group#>, <#dispatch_queue_t queue#>, ^{
//執行圖片合併等操作
……..
//回到主線程顯示
dispatch_async(dispatch_get_main_queue(), ^{
//顯示內容等操作
});
});
要求:
//例如:
//1分別下載兩張圖片:大圖片
logo
//2合併兩張圖片
//3顯示到一個imageView上
//百度logo http://img.baidu.com/img/baike/logo-baike.png
//2合併兩張圖片
//3顯示到一個imageView上
//百度logo http://img.baidu.com/img/baike/logo-baike.png
此處還可以用異步併發隊列來實現此功能