u=1546308334,1185521960&fm=21&gp=0.jpg
GCD
簡介
- 1.旨在代替NSThread等線程技術
- 2.能夠充分利用多核的特點
- 3.用到的兩個核心概念:隊列(并發(fā)+串行)+任務(同步+異步)
- 有一點需要注意:異步函數(shù)具有開啟線程的能力,而同步函數(shù)不會開啟線程
基本使用
- 01 異步函數(shù)+并發(fā)隊列:開啟多條線程,并發(fā)執(zhí)行任務(最常用)
- 02 異步函數(shù)+串行隊列:開啟一條線程见坑,串行執(zhí)行任務
- 03 同步函數(shù)+并發(fā)隊列:不開線程丁鹉,在當前線程里串行執(zhí)行任務
- 04 同步函數(shù)+串行隊列:不開線程,在當前線程里串行執(zhí)行任務
- 05 異步函數(shù)+主隊列:不開線程日川,在主線程中串行執(zhí)行任務
- 06 同步函數(shù)+主隊列:不開線程,串行執(zhí)行任務(注意死鎖發(fā)生)
常用代碼示例:
- 1.異步+并發(fā)
//異步+并發(fā)(創(chuàng)建多個線程,并發(fā)執(zhí)行)
-(void)asyncConcurrent{
/*
第一個參數(shù):C語言的字符串 給隊列起一個名字
第二個參數(shù):類型
DISPATCH_QUEUE_CONCURRENT 并發(fā)隊列
DISPATCH_QUEUE_SERIAL 串行隊列
*/
//創(chuàng)建并發(fā)隊列
dispatch_queue_t queue=dispatch_queue_create("wujian.com.con", DISPATCH_QUEUE_CONCURRENT);
//封裝任務并把任務添加到隊列當中
dispatch_async(queue, ^{
NSLog(@"1--------------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2--------------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"3--------------%@",[NSThread currentThread]);
});
}
- 2.異步+串行
-(void)asyncSerial{
NSLog(@"開始---");
dispatch_queue_t queue=dispatch_queue_create("lslslslsll.com", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"1--------------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2--------------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"3--------------%@",[NSThread currentThread]);
});
NSLog(@"結(jié)束---");
}
注意:此處運行會發(fā)現(xiàn)先打印“開始--”南吮,然后打印“結(jié)束--”,在這之后再處理這兩者中間的具體任務誊酌,這其實是異步函數(shù)的一個特點部凑,異步函數(shù)采用的是回調(diào)的機制露乏,像打印這種簡單的操作,就直接執(zhí)行了涂邀,而對于異步函數(shù)里的任務施无,在其他操作完成之后再去執(zhí)行,這樣做會防止死鎖的發(fā)生必孤。
- 3.同步+串行(在當前線程中串行執(zhí)行)
-(void)syncSerial{
dispatch_queue_t queue=dispatch_queue_create("com.sssss", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"1--------------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2--------------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"3--------------%@",[NSThread currentThread]);
});
}
- 4.同步+并發(fā)(不會創(chuàng)建線程猾骡,在當前線程中串行執(zhí)行)
-(void)syncConcurrent{
//自己創(chuàng)建的并發(fā)隊列
// dispatch_queue_t queue=dispatch_queue_create("ldsjfl.com", DISPATCH_QUEUE_CONCURRENT);
//獲取全局隊列(用法與上面幾乎無異)
dispatch_queue_t queue=dispatch_get_global_queue(0, 0);
dispatch_sync(queue, ^{
NSLog(@"1--------------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2--------------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"3--------------%@",[NSThread currentThread]);
});
}
- 5.異步+主隊列(與主線程相關):在主線程中串行執(zhí)行,由于異步的執(zhí)行特點敷搪,所以不會造成死鎖
-(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]);
});
}
- 6.同步+主隊列:會造成死鎖(在子線程中不會有死鎖發(fā)生)
- 如果主隊列中有任務,那么主隊列會安排主線程來執(zhí)行當前隊列中的任務,但是在調(diào)度之前會先檢查主線程的狀態(tài),如果主線程在忙那么就暫停調(diào)度隊列中的任務,等到主線程空閑的時候再調(diào)度(而此處的主線程剛好在執(zhí)行自身這個函數(shù)) (只有主隊列關心主線程忙不忙)
-(void)syncMainQueue{
NSLog(@"ssss");
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]);
});
}
獲得串行隊列的兩種途徑
- 1.通過函數(shù)自己創(chuàng)建
dispatch_queue_t queue=dispatch_queue_create("lslslslsll.com", DISPATCH_QUEUE_SERIAL);
- 2.獲得系統(tǒng)的主隊列
dispatch_queue_t queue=dispatch_get_main_queue();
獲得全局隊列的兩種途徑
- 1.通過函數(shù)自己創(chuàng)建
dispatch_queue_t queue=dispatch_queue_create("wujian.com.con", DISPATCH_QUEUE_CONCURRENT);
- 2.獲得系統(tǒng)的全局隊列(建議使用這種方法)
//第一個參數(shù)是隊列的優(yōu)先級兴想,可以傳0表示默認,第二個參數(shù)暫時用不上赡勘,是蘋果預留的參數(shù)嫂便,傳0即可。
dispatch_queue_t queue=dispatch_get_global_queue(0, 0);
GCD中的線程通信
- (void)viewDidLoad {
[super viewDidLoad];
//開子線程
//01 獲得全局并發(fā)隊列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
//02 使用異步函數(shù)+并發(fā)隊列
dispatch_async(queue, ^{
//03 確定URL
NSURL *url = [NSURL URLWithString:@"http://XXXXX.jpg"];
//04 把圖片的二進制數(shù)據(jù)下載到本地
NSData *data = [NSData dataWithContentsOfURL:url];
//05 轉(zhuǎn)換格式
UIImage *image = [UIImage imageWithData:data];
NSLog(@"耗時操作---%@",[NSThread currentThread]);
//06 顯示圖片(回到主線程闸与,其實是一種嵌套的模式)
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
NSLog(@"UI操作---%@",[NSThread currentThread]);
});
});
}