GCD是蘋果為多核并行運算提出的解決方案,全稱是Grand Central
Dispatch.GCD是純C語言的,它會自動管理線程的生命周期,所以我們只需要告訴GCD想要執行什么任務不需要編寫任何線程管理的代碼.
GCD有兩個核心的概念:
1.任務 執行什么操作.
2.隊列 用來存放任務.
GCD使用的兩個步驟:
1.定制任務
2.把任務添加到隊列中
GCD有兩種類型的隊列:
1.并發隊列
2.串行隊列
并發隊列:把前一個任務取出來之后就繼續執行下一個任務
串行隊列:把前一個任務取出來之后,等這個任務全部執行完畢在執行后面的任務.
主隊列是一種特殊的串行的隊列,所有添加到主隊列的任務都將在主線程中執行.
注意:GCD在使用時具體開幾條線程并不是由任務的數量決定的,由系統自動決定.
隊列的創建方式:
1.第一種
第一個參數:C語言的字符串 給隊列起一個名字
第二個參數:類型
DISPATCH_QUEUE_CONCURRENT 并發隊列
DISPATCH_QUEUE_SERIAL 串行隊列
dispatch_queue_create(<#const char *label#>, <#dispatch_queue_attr_t attr#>)
2.第二種
第一個參數:隊列的優先級 DISPATCH_QUEUE_PRIORITY_DEFAULT 默認 == 0
第二個參數:
dispatch_get_global_queue(<#long identifier#>, <#unsigned long flags#>)
3.主隊列 dispatch_get_main_queue();
GCD的幾種隊列組合:
1.異步函數+并發隊列 開啟多條線程,并發執行任務
2.異步函數+串行隊列 開啟一條線程,串行執行任務
3.同步函數+串行隊列 不開線程,串行執行任務
4.同步函數+并發隊列 不開線程,并發執行任務
5.異步函數+主隊列 不開線程,在主線程串行執行任務
6.同步函數+主隊列 不開線程,串行執行任務(發生死鎖)
GCD線程間的通信:
1.獲取全局并發隊列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
2.使用異步函數加并發隊列
dispatch_async(queue, ^{
03.確定url
NSURL *url = [NSURL URLWithString:@"http://pic.yesky.com/uploadImages/2014/064/OH4H8VH65DW9.jpg"];
04.把圖片的二進制數據下載到本地
NSData *data = [NSData dataWithContentsOfURL:url];
05.轉換格式
UIImage *image = [UIImage imageWithData:data];
//06 顯示圖片(回到主線程)
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
}
GCD常用的函數
01.一次性代碼
特點:
整個程序運行過程只會執行一次.
保證線程的安全
常用與單例模式的實現中.
-(void)once
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"_________________");
});
}
02.柵欄函數
控制任務的執行順序.等之前的所有任務都執行完畢之后執行柵欄函數中的任務,等我的任務執行完畢之后再執行后面的任務.
前面的和后面的任務都是并發執行的.
注意點:柵欄函數不能使用全局并發隊列
-(void)barrier
{
//獲得隊列
dispatch_queue_t queue = dispatch_queue_create("download", DISPATCH_QUEUE_CONCURRENT);
//異步函數
dispatch_async(queue, ^{
NSLog(@"1-----%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2-----%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"3-----%@",[NSThread currentThread]);
});
dispatch_barrier_async(queue, ^{
NSLog(@"____________________");
});
dispatch_async(queue, ^{
NSLog(@"4-----%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"5-----%@",[NSThread currentThread]);
});
03.延遲執行
01.proform方法
02.NSTimer
03.GCD
-(void)afterDelay
{
//01. 2.0 秒之后再調用run方法
[self performSelector:@selector(run) withObject:nil afterDelay:2.0];
//方法二 NSTimer
[NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(run) userInfo:nil repeats:NO];
//方法三 GCD
先等2s 再把任務提交到隊列
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"run");
});
04.快速迭代
開多個線程并發完成迭代操作
dispatch_apply(subpaths.count, queue, ^(size_t index) {
});
05.隊列組
//創建隊列組
dispatch_group_t group = dispatch_group_create();
//隊列組中的任務執行完畢之后,執行該函數
dispatch_group_notify(dispatch_group_t group,dispatch_queue_t queue,dispatch_block_t block);
dispatch_group_enter(group);//執行該函數后,后面異步執行的block會被gruop監聽
dispatch_group_leave(group);//異步block中,所有的任務都執行完畢,最后離開群組
注意:dispatch_group_enter|dispatch_group_leave必須成對使用