理解
串行队列: 先入先出,执行完第一个再执行第二个。
并发队列: 先执行第一个,第一个还没执行完时便可以执行第二个。
并发是编程角度上的上同时,一个CPU也可以,两个任务交替进行
并行是物理CPU上同时执行(至少两个CPU)
GCD中的同步和异步是针对任务的执行来说的
同步:执行完一个函数后在执行下一个函数,不会开启新线程
异步:不管当前函数,都会继续执行下一个函数,开启新线程
同步和异步的主要区别是向队列里面添加任务时是立即返回还是等添加的任务完成之后再返回。
主要应用场景:
- 串行队列,同步任务(主线程中执行,不开启新线程,顺序执行)
- 串行队列,异步任务(开启一条新线程,顺序执行,需要在主线程刷新ui)
- 并发队列,同步任务(不开启新线程,顺序执行)
- 并发队列,异步任务(开启多条线程,无顺序执行,需要在主线程刷新ui)
- 全局任务/并发队列
- 延迟执行任务 (dispatch_after)
- 一次执行任务 (dispatch_once)
- 调度组 (用一个调度组,可以监听全局队列的任务)
- 主队列异步任务
- 主队列同步任务(死锁)
- 主队列同步任务(不死锁)
串行队列,同步任务
//创建串行任务
dispatch_queue_t queue = dispatch_queue_create("串行队列", DISPATCH_QUEUE_SERIAL);
//执行同步任务
for(int i = 0; i < 10; ++i){
dispatch_sync(queue, ^{
NSString *str = [NSString stringWithFormat:@"线程=%@ 角标:%d",[NSThread currentThread],i];
});
}
//主线程中执行,不开启新线程,顺序执行
串行队列,异步任务
dispatch_queue_t q = dispatch_queue_create("串行队列", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i < 10; i++) {
//在主线程中刷新UI
dispatch_async(q, ^{
NSString *str = [NSString stringWithFormat:@"线程=%@ 角标:%d",[NSThread currentThread],i];
NSLog(@"%@",str);
});
}
//开启一条新线程,顺序执行
并发队列,同步任务
dispatch_queue_t q = dispatch_queue_create("并发队列", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 10; i++) {
dispatch_sync(q, ^{
NSString *str = [NSString stringWithFormat:@"线程=%@ 角标:%d",[NSThread currentThread],i];
NSLog(@"%@",str);
});
}
并发队列,异步任务
dispatch_queue_t q = dispatch_queue_create("并发队列", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 10; i++) {
dispatch_async(q, ^{
//在主线程中刷新UI
NSString *str = [NSString stringWithFormat:@"线程=%@ 角标:%d",[NSThread currentThread],i];
NSLog(@"%@",str);
});
}
//开启多条线程,无顺序执行
调度组
问题:iOS 有a、b、c、d 4个异步请求,如何判断a、b、c、d都完成执行?
[答案:用调度组]
/*用一个 调度组 监听全局队列的任务*/
//创建一个全局队列
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
//创建一个调度组
dispatch_group_t g = dispatch_group_create();
//添加任务,让队列调度
dispatch_group_async(g, q, ^{
NSString *log = [NSString stringWithFormat:@"下载第一个文件%@", [NSThread currentThread]];
NSLog(@"%@",str);
});
dispatch_group_async(g, q, ^{
[NSThread sleepForTimeInterval:5];//延迟5秒
NSString *log = [NSString stringWithFormat:@"下载第二个文件%@", [NSThread currentThread]];
NSLog(@"%@",str);
});
dispatch_group_async(g, q, ^{
NSString *log = [NSString stringWithFormat:@"下载第三个文件%@", [NSThread currentThread]];
NSLog(@"%@",str);
});
//所有任务执行完成后,通知调度组
dispatch_group_notify(g, dispatch_get_main_queue(), ^{
NSString *log = [NSString stringWithFormat:@"执行完毕:%@",[NSThread currentThread]];
NSLog(@"%@",str);
});
主队列异步任务
问题:iOS 有a、b、c、d 4个异步请求,如果需要a、b、c、d顺序执行,该如何实现?
答案:[用主队列异步任务]
//创建一个队列,启动主线程就可以获取到主队列。
dispatch_queue_t q = dispatch_get_main_queue();
//添加异步任务
dispatch_async(q, ^{
NSLog(@"添加异步任务,并延迟5秒");
[NSThread sleepForTimeInterval:5];
NSString *log1 = [NSString stringWithFormat:@"异步任务0%@", [NSThread currentThread]];
NSLog(@"%@",str);
});
dispatch_async(q, ^{
[self.logView insert:@"添加异步任务,并延迟1秒"];
[NSThread sleepForTimeInterval:1];
NSString *log1 = [NSString stringWithFormat:@"异步任务1%@", [NSThread currentThread]];
NSLog(@"%@",str);
});
dispatch_async(q, ^{
[self.logView insert:@"添加异步任务,并延迟10秒"];
[NSThread sleepForTimeInterval:10];
NSString *log1 = [NSString stringWithFormat:@"异步任务2%@", [NSThread currentThread]];
NSLog(@"%@",str);
});
主队列同步任务(死锁)
NSLog(@"能执行到我");
dispatch_queue_t q = dispatch_get_main_queue();
//同步任务 死锁
dispatch_sync(q, ^{
NSLog(@"不能执行到我");
});
NSLog(@"不能执行到我");
//同步任务死锁,运行会报错。
主队列同步任务(不死锁)
void (^task)(void) = ^ {
NSLog(@"能执行到我 %@", [NSThread currentThread]);
dispatch_queue_t q = dispatch_get_main_queue();
//.同步任务(不死锁)
dispatch_sync(q, ^{
NSLog(@"能执行到我 %@", [NSThread currentThread]);
});
NSLog(@"能执行到我");
};
dispatch_async(dispatch_get_global_queue(0, 0), task);
//同步任务不死锁,同步任务在主线程中执行,其它任务都在子线程中执行。