1、GCD是什麼。安全
GCD 是 libdispatch 的市場名稱,而 libdispatch 做爲 Apple 的一個庫,爲併發代碼在多核硬件(跑 iOS 或 OS X )上執行提供有力支持。網絡
它具備如下優勢:
1.GCD 能經過推遲昂貴計算任務並在後臺運行它們來改善你的應用的響應性能。
2.GCD 提供一個易於使用的併發模型而不單單只是鎖和線程,以幫助咱們避開併發陷阱。
3.GCD 具備在常見模式(例如單例)上用更高性能的原語優化你的代碼的潛在能力。
併發
2、系統提供的用法
app
爲了方便GCD的使用,蘋果提供了一些方法方便咱們將Block放在主線程或者後臺線程或者延後執行。異步
//子線程執行async
dispatch_async(dispatch_get_global_queue(0, 0), ^{函數
//something性能
});優化
//主線程執行ui
dispatch_sync(dispatch_get_main_queue(), ^{
//something
});
//一次性執行
static dispatch_once_t onceTaken;
dispatch_once(&onceTaken, ^{
//something
});
//延遲2S加載
double delayInSecond = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSecond * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^{
//something
});
3、應用---延時
(1)調用NSObject的方法 [self performSelector:@selector(run) withObject:nil afterDelay:2.0]; // 2秒後再調用self的run方法 (2)使用GCD函數 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 2秒後執行這裏的代碼... // 默認在主線程執行,你也能夠併發,在子線程執行 }); (3)使用NSTimer [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:NO];
應用---一次性執行
使用dispatch_once函數能保證某段代碼在程序運行過程當中只被執行1次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 只執行1次的代碼(這裏面默認是線程安全的)
});
// 適合作資源的加載,可是和懶加載不一樣,它一旦加載,加載一次,別人就不能加載,整個程序哦,全局性
應用---快速迭代
使用dispatch_apply函數能進行快速迭代遍歷
dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index){
// 執行10次代碼,index順序不肯定
// 和for循環不一樣,不是有序的
// 它是同時併發遍歷,一塊兒作事情,快速遍歷迭代
// 好比剪切圖片的例子
});
應用---隊列組
有這麼1種需求
首先:分別異步執行2個耗時的操做
其次:等2個異步操做都執行完畢後,再回到主線程執行操做
若是想要快速高效地實現上述需求,能夠考慮用隊列組。
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 執行1個耗時的異步操做 });
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 執行1個耗時的異步操做 });
dispatch_group_notify(group, dispatch_get_main_queue(), ^{ // 等前面的異步操做都執行完畢後,回到主線程... });
Demo-核心代碼
- (void)group
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 建立一個隊列組
dispatch_group_t group = dispatch_group_create();
// 1.下載圖片1
dispatch_group_async(group, queue, ^{
// 圖片的網絡路徑
NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];
// 加載圖片
NSData *data = [NSData dataWithContentsOfURL:url];
// 生成圖片
self.image1 = [UIImage imageWithData:data];
});
// 2.下載圖片2
dispatch_group_async(group, queue, ^{
// 圖片的網絡路徑
NSURL *url = [NSURL URLWithString:@"http://pic38.nipic.com/20140228/5571398_215900721128_2.jpg"];
// 加載圖片
NSData *data = [NSData dataWithContentsOfURL:url];
// 生成圖片
self.image2 = [UIImage imageWithData:data];
});
// 能夠用barrier,先作前面兩個,再作後面的任務
// 這裏用隊列組,前面的任務都放進本身的一個組,你的隊列屬於本身的組,前面兩個組無論你誰先執行,都執行完後,再執行dispatch_group_notify裏面的東西
// 3.將圖片一、圖片2合成一張新的圖片
// 圖片合成用繪圖技術
dispatch_group_notify(group, queue, ^{
// 開啓新的圖形上下文
UIGraphicsBeginImageContext(CGSizeMake(100, 100));
// 繪製圖片
[self.image1 drawInRect:CGRectMake(0, 0, 50, 100)];
[self.image2 drawInRect:CGRectMake(50, 0, 50, 100)];
// 取得上下文中的圖片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 結束上下文
UIGraphicsEndImageContext();
// 回到主線程顯示圖片
dispatch_async(dispatch_get_main_queue(), ^{
// 4.將新圖片顯示出來
self.imageView.image = image;
});
});
}
/** * 快速迭代 */
- (void)apply
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSString *from = @"/Users/xiaomage/Desktop/From";
NSString *to = @"/Users/xiaomage/Desktop/To";
// 這裏剪切文件徹底能夠同時進行,用子線程包起來
NSFileManager *mgr = [NSFileManager defaultManager];
NSArray *subpaths = [mgr subpathsAtPath:from];
dispatch_apply(subpaths.count, queue, ^(size_t index) {
NSString *subpath = subpaths[index];
NSString *fromFullpath = [from stringByAppendingPathComponent:subpath];
NSString *toFullpath = [to stringByAppendingPathComponent:subpath];
// 剪切
[mgr moveItemAtPath:fromFullpath toPath:toFullpath error:nil];
NSLog(@"%@---%@", [NSThread currentThread], subpath);
});
}
/** * 傳統文件剪切 */
- (void)moveFile
{
NSString *from = @"/Users/xiaomage/Desktop/From";
NSString *to = @"/Users/xiaomage/Desktop/To";
NSFileManager *mgr = [NSFileManager defaultManager];
NSArray *subpaths = [mgr subpathsAtPath:from];
for (NSString *subpath in subpaths) {
NSString *fromFullpath = [from stringByAppendingPathComponent:subpath];
NSString *toFullpath = [to stringByAppendingPathComponent:subpath];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 剪切
[mgr moveItemAtPath:fromFullpath toPath:toFullpath error:nil];
});
}
}
- (void)once
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"------run");
});
}
/** * 延遲執行 */
- (void)delay
{
NSLog(@"touchesBegan-----");
// [self performSelector:@selector(run) withObject:nil afterDelay:2.0];
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// NSLog(@"run-----");
// });
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:NO];
}
- (void)run
{
NSLog(@"run-----");
}
- (void)barrier
{
dispatch_queue_t queue = dispatch_queue_create("12312312", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"----1-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----2-----%@", [NSThread currentThread]);
});
dispatch_barrier_async(queue, ^{
NSLog(@"----barrier-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----3-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----4-----%@", [NSThread currentThread]);
});
}