##什么是GCD:
1、GCD是蘋果開發的一個多核編程的解決方法,和其它多線程技術方案相比,使用起來更加簡單和方便. ?
2、純C語言,提供了非常多強大的函數
## GCD的優勢: ?
1、GCD是蘋果公司為多核的并行運算提出的解決方案 ??
2、GCD會自動利用更多的CPU內核(比如雙核、四核) ??
3、GCD會自動管理線程的生命周期(創建線程、調度任務、銷毀線程)
4、程序員只需要告訴GCD想要執行什么任務,不需要編寫任何線程管理代碼
##隊列和任務:
GCD中有2個核心概念 ?
任務:執行什么操作,用block來封裝任務。
隊列:用來存放任務。
將任務添加到隊列中GCD會自動將隊列中的任務取出,放到對應的線程中執行。
任務的取出遵循隊列的FIFO原則:先進先出,后進后出 。
隊列的類型
并發隊列:可以讓多個任務并發(同時)執行(自動開啟多個線程同時執行任務),并發功能只有在異步(dispatch_async)函數下才有效。
1、獲得全局的并發隊列
~~~
//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// 后臺
~~~
串行隊列:讓任務一個接著一個地執行(一個任務執行完畢后,再執行下一個任務)。 ?
1、使用dispatch_queue_create函數創建串行隊列
~~~
//const char *label:隊列名稱
//dispatch_queue_attr_t attr:隊列屬性,一般用NULL即可
dispatch_queue_t queue = dispatch_queue_create("cn.XXX",NULL);
~~~
~~~
dispatch_release(queue); // 非ARC需要釋放手動創建的隊列
~~~
2、使用主隊列(跟主線程相關聯的隊列),主隊列是GCD自帶的一種特殊的串行隊列
放在主隊列中的任務,都會放到主線程中執行
使用dispatch_get_main_queue()獲得主隊列
~~~
dispatch_queue_t queue = dispatch_get_main_queue();
~~~
執行任務:
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
2、異步:可以在新的線程中執行任務,具備開啟新線程的能力。 dispatch_async
隊列和執行任務方式組合分析:
ps 特別注意:使用sync函數往當前串行隊列中添加任務,會卡住當前的串行隊列

~~~
/**
* 異步全局并發
* async并發隊列(最常用)
* 會創建線程,一般同時開多條
* 并發執行
**/
-(void)asyncGlobalQueue{
//獲取全局并發隊列
//dispatch_queue_priority_t priority:隊列的優先級
//unsigned long flags:此參數暫時無用,用0即可
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//將任務添加到全局隊列中去異步執行
dispatch_async(queue, ^{
NSLog(@"------下載圖片1----%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下載圖片2-----%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----下載圖片3------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下載圖片4----%@",[NSThread currentThread]);
});
}
/**
* 串行隊列(有時候會用)
* 會創建線程,一般只開一條
* 串行執行,(一個任務執行完畢后再執行下一個任務)
**/
-(void)asyncSerialQueue{
//創建串行隊列
//const char *label:隊列名稱
//dispatch_queue_attr_t attr:隊列屬性,一般用NULL即可
dispatch_queue_t queue = dispatch_queue_create("cn.XXX",NULL);
//將任務添加到串行隊列中 異步執行
dispatch_async(queue,^{
NSLog(@"--------下載圖片1---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下載圖片2---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下載圖片3---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下載圖片4---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下載圖片5---------%@",[NSThread currentThread]);
});
}
/**
* async --主隊列(很常用)
**/
-(void)asyncMainQueue{
//主隊列(添加到主隊列中的任務,都會自動放到主線程中去執行)
dispatch_queue_t queue = dispatch_get_main_queue();
//添加任務到主隊列中異步執行
dispatch_async(queue, ^{
NSLog(@"--------下載圖片1---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下載圖片2---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下載圖片3---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下載圖片4---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下載圖片5---------%@",[NSThread currentThread]);
});
}
/**
* sync --主隊列(不能用,會卡死)
**/
-(void)syncMainQueue{
//主隊列(添加到主隊列中的任務,都會自動放到線程中去執行)
dispatch_queue_t queue = dispatch_get_main_queue();
//將任務添加到主隊列中同步執行
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片1---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片2---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片3---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片4---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片5---------%@",[NSThread currentThread]);
});
}
/**
* sync --并發隊列
* 不會創建線程
* 串行執行(一個任務執行完畢后再執行下一個任務)
* 并發隊列失去了并發的功能
**/
-(void)syncGlobalQueue{
//獲取全局的并發隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//將任務添加到全局并發隊列中同步執行
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片1---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片2---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片3---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片4---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片5---------%@",[NSThread currentThread]);
});
}
/**
* sync --串行隊列
* 不會創建線程
* 串行執行(一個任務執行完畢后再執行下一個任務)
**/
-(void)syncSerialQueue{
//創建一個串行隊列
dispatch_queue_t queue = dispatch_queue_create("cn.xxx", NULL);
//將任務添加到串行隊列中同步執行
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片1---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片2---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片3---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片4---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下載圖片5---------%@",[NSThread currentThread]);
});
}
~~~
一次性執行:
~~~
//一次性執行
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//<#code to be executed once#>
});
~~~
延時執行:
~~~
//延時執行(2秒)
double delayInSeconds = 2;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// <#code to be executed after a specified delay#>
});
~~~
線程組:后臺并發執行線程,等所有線程執行結束后再匯總執行結果
~~~
//1、獲取線程組
dispatch_group_t group = dispatch_group_create();
//2、并行執行線程
dispatch_group_async(group, queue, ^{
//并發執行線程一
);
ispatch_group_async(group, queue, ^{
//并發執行線程二
});
//3、所有線程執行完成后調用
dispatch_group_notify(group, queue, ^{
//匯總結果
});
~~~
## 線程間通信
從子線程回到主線程
~~~
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
? ? // 執行耗時的異步操作...
? ? ? dispatch_async(dispatch_get_main_queue(), ^{
? ? ? ? // 回到主線程,執行UI刷新操作
? ? ? ? });
});
~~~
例子:子線程下載圖片,下載后更新界面的imageView.
~~~
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
//子線程下載圖片
NSURL *url = [NSURL URLWithString:@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
//回到主線程
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue, ^{
self.imageView.image = image;
});
});
}
~~~
- 前言
- iOS開發實踐之SQLite3
- iOS開發實踐之FMDB
- Obj-C與javascript交互之WebViewJavascriptBridge
- iOS開發實踐之UIWebView
- iOS開發實踐之多線程(基本概念)
- iOS開發實踐之多線程(NSThread)
- iOS開發實踐之多線程(GCD)
- iOS開發實踐之多線程(單例模式)
- iOS開發實踐之xib加載注意問題
- iOS開發實踐之多線程(NSOperation)
- iOS開發實踐之cell下載圖片(NSOperation)
- iOS開發實踐之cell下載圖片(自定義NSOperation)
- iOS開發實踐之cell下載圖片(SDWebImage)
- iOS開發實踐之JSON
- iOS開發實踐之XML
- iOS開發實踐之GET和POST請求
- iOS開發實踐之網絡檢測Reachability
- iOS開發實踐之MD5加密