iOS —— 關於GCD的理解和使用
一.什麽是GCD
Grand Central Dispatch (強大的中樞調度器) ,是異步執行任務的技術之一。純C語言,有很多強大的函數。
二.GCD的優勢
(1)GCD是蘋果公司為多核並行運算提供的解決方案。
(2)GCD會自動利用更多的CPU內核(雙核,四核等)。
(3)GCD會自動管理線程的生命周期(創建線程、調度任務、銷毀線程)
(4)程序員只需要告訴GCD想要執行什麽任務,不需要編寫任何線程管理代碼
三.任務和隊列
GCD中有兩個很核心的概念:任務和隊列。
任務:你要執行的操作
隊列:用來存放任務
四.執行任務的兩種方式
1.同步:在當前線程中執行
異步:在另一個線程中執行
2. GCD中有兩個用來執行任務的函數:
(1)用同步的方式執行任務 dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
(2)用異步的方式執行任務 dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
五.隊列的兩種類型
(1) 串行隊列:在一個線程中依次執行(dispatch_sync)
並發隊列:多個任務同時執行 (開啟多個線程同時執行任務)(dispatch_async)
(2)同步、異步、串行、並發 說明
同步和異步決定了能不能開啟新線程
同步:在當前線程中執行任務,不具備開啟新線程的能力
異步:在新的線程中執行任務,具備開啟新線程的能力
串行和並行決定了任務的執行形式
串行:任務依次執行
並行:多個任務同時並發執行
註意:只有在異步的時候開啟線程,所以只能在異步的時候並發執行任務。
六.獲取隊列的函數
1獲取串行隊列
(1)使用dispatch_queue_create函數創建串行隊列
dispatch_queue_t queue = dispatch_queue_create(" wendingding", NULL); // 創建
(2)使用主隊列(跟主線程相關聯的隊列)
dispatch_queue_t queue = dispatch_get_main_queue();
2.獲取並行隊列
使用dispatch_get_global_queue函數獲得全局的並發隊列
dispatch_queue_t dispatch_get_global_queue(dispatch_queue_priority_t priority,unsigned long flags); // 此參數暫時無用,用0即可
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 獲得全局並發隊列
說明:全局並發隊列的優先級
#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 // 後臺
七、GCD的基本使用
1. 串行隊列 + 同步執行
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"主線程----%@",[NSThread mainThread]);
//創建串行隊列
dispatch_queue_t queue = dispatch_queue_create("dengdeng", 0);
//添加任務到隊列中去
dispatch_sync(queue, ^{
NSLog(@"下載圖片1 ----- %@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"下載圖片2 ----- %@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"下載圖片3 ----- %@",[NSThread currentThread]);
});
}
打印結果如下:
2017-06-16 16:56:16.331 GCDTest[14678:2213850] 主線程----<NSThread: 0x608000073000>{number = 1, name = main}
2017-06-16 16:56:16.332 GCDTest[14678:2213850] 下載圖片1 ----- <NSThread: 0x608000073000>{number = 1, name = main}
2017-06-16 16:56:16.333 GCDTest[14678:2213850] 下載圖片2 ----- <NSThread: 0x608000073000>{number = 1, name = main}
2017-06-16 16:56:16.333 GCDTest[14678:2213850] 下載圖片3 ----- <NSThread: 0x608000073000>{number = 1, name = main}
2. 並行隊列 + 同步執行
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"主線程----%@",[NSThread mainThread]);
//創建串行隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//第一個參數為串行隊列的名稱,是c語言的字符串
//第二個參數為隊列的屬性,一般來說串行隊列不需要賦值任何屬性,所以通常傳空值(NULL)
//添加任務到隊列中去
dispatch_sync(queue, ^{
for (int i = 0; i < 2 ; i ++) {
NSLog(@"下載圖片1 ----- %@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 2 ; i ++) {
NSLog(@"下載圖片2 ----- %@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 2 ; i ++) {
NSLog(@"下載圖片3 ----- %@",[NSThread currentThread]);
}
});
}
打印結果:
2017-06-16 17:29:58.848 GCDTest[14951:2249589] 主線程----<NSThread: 0x600000068600>{number = 1, name = main}
2017-06-16 17:29:58.849 GCDTest[14951:2249589] 下載圖片1 ----- <NSThread: 0x600000068600>{number = 1, name = main}
2017-06-16 17:29:58.849 GCDTest[14951:2249589] 下載圖片1 ----- <NSThread: 0x600000068600>{number = 1, name = main}
2017-06-16 17:29:58.849 GCDTest[14951:2249589] 下載圖片2 ----- <NSThread: 0x600000068600>{number = 1, name = main}
2017-06-16 17:29:58.849 GCDTest[14951:2249589] 下載圖片2 ----- <NSThread: 0x600000068600>{number = 1, name = main}
2017-06-16 17:29:58.849 GCDTest[14951:2249589] 下載圖片3 ----- <NSThread: 0x600000068600>{number = 1, name = main}
2017-06-16 17:29:58.849 GCDTest[14951:2249589] 下載圖片3 ----- <NSThread: 0x600000068600>{number = 1, name = main}
註:同步執行不會開啟新線程
2. 串行隊列 + 異步執行
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"主線程----%@",[NSThread mainThread]);
//創建串行隊列
dispatch_queue_t queue = dispatch_queue_create("dengdeng", 0);
//第一個參數為串行隊列的名稱,是c語言的字符串
//第二個參數為隊列的屬性,一般來說串行隊列不需要賦值任何屬性,所以通常傳空值(NULL)
//添加任務到隊列中去
dispatch_async(queue, ^{
NSLog(@"下載圖片1 ----- %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"下載圖片2 ----- %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"下載圖片3 ----- %@",[NSThread currentThread]);
});
}
2017-06-16 17:15:09.901 GCDTest[14851:2235809] 主線程----<NSThread: 0x60800007ad80>{number = 1, name = main}
2017-06-16 17:15:09.901 GCDTest[14851:2235848] 下載圖片1 ----- <NSThread: 0x608000262c40>{number = 3, name = (null)}
2017-06-16 17:15:09.901 GCDTest[14851:2235848] 下載圖片2 ----- <NSThread: 0x608000262c40>{number = 3, name = (null)}
2017-06-16 17:15:09.902 GCDTest[14851:2235848] 下載圖片3 ----- <NSThread: 0x608000262c40>{number = 3, name = (null)}
註:開啟了新的線程,在新的線程上,這三個任務是串行的。
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"主線程----%@",[NSThread mainThread]);
//創建串行隊列
dispatch_queue_t queue = dispatch_queue_create("dengdeng", 0);
//第一個參數為串行隊列的名稱,是c語言的字符串
//第二個參數為隊列的屬性,一般來說串行隊列不需要賦值任何屬性,所以通常傳空值(NULL)
//添加任務到隊列中去
dispatch_async(queue, ^{
NSLog(@"下載圖片1 ----- %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"下載圖片2 ----- %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"下載圖片3 ----- %@",[NSThread currentThread]);
});
for (int i = 0; i < 3 ; i ++) {
NSLog(@"下載圖片main ----- %@",[NSThread currentThread]);
}
}
2017-06-16 17:19:06.154 GCDTest[14870:2240144] 主線程----<NSThread: 0x60800007d200>{number = 1, name = main}
2017-06-16 17:19:06.155 GCDTest[14870:2240144] 下載圖片main ----- <NSThread: 0x60800007d200>{number = 1, name = main}
2017-06-16 17:19:06.155 GCDTest[14870:2240278] 下載圖片1 ----- <NSThread: 0x600000268400>{number = 3, name = (null)}
2017-06-16 17:19:06.155 GCDTest[14870:2240144] 下載圖片main ----- <NSThread: 0x60800007d200>{number = 1, name = main}
2017-06-16 17:19:06.155 GCDTest[14870:2240278] 下載圖片2 ----- <NSThread: 0x600000268400>{number = 3, name = (null)}
2017-06-16 17:19:06.155 GCDTest[14870:2240144] 下載圖片main ----- <NSThread: 0x60800007d200>{number = 1, name = main}
2017-06-16 17:19:06.155 GCDTest[14870:2240278] 下載圖片3 ----- <NSThread: 0x600000268400>{number = 3, name = (null)}
註:開啟的新線程和主線程的關系:並發執行
4. 並行隊列 + 異步執行
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"主線程----%@",[NSThread mainThread]);
//創建串行隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//第一個參數為串行隊列的名稱,是c語言的字符串
//第二個參數為隊列的屬性,一般來說串行隊列不需要賦值任何屬性,所以通常傳空值(NULL)
//添加任務到隊列中去
dispatch_async(queue, ^{
for (int i = 0; i < 3 ; i ++) {
NSLog(@"下載圖片1 ----- %@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 3 ; i ++) {
NSLog(@"下載圖片2 ----- %@",[NSThread currentThread]);
}
});
}
2017-06-16 17:25:40.722 GCDTest[14920:2245705] 主線程----<NSThread: 0x60000007f240>{number = 1, name = main}
2017-06-16 17:25:40.725 GCDTest[14920:2245740] 下載圖片1 ----- <NSThread: 0x60000026b9c0>{number = 3, name = (null)}
2017-06-16 17:25:40.725 GCDTest[14920:2245742] 下載圖片2 ----- <NSThread: 0x608000264b00>{number = 4, name = (null)}
2017-06-16 17:25:40.752 GCDTest[14920:2245740] 下載圖片1 ----- <NSThread: 0x60000026b9c0>{number = 3, name = (null)}
2017-06-16 17:25:40.753 GCDTest[14920:2245742] 下載圖片2 ----- <NSThread: 0x608000264b00>{number = 4, name = (null)}
2017-06-16 17:25:40.755 GCDTest[14920:2245740] 下載圖片1 ----- <NSThread: 0x60000026b9c0>{number = 3, name = (null)}
2017-06-16 17:25:40.756 GCDTest[14920:2245742] 下載圖片2 ----- <NSThread: 0x608000264b00>{number = 4, name = (null)}
註:開啟多個線程,並發執行任務
iOS —— 關於GCD的理解和使用