GCD 核心概念:将任务添加到队列,指定任务执行的方法
总结:
-开不开线程,取决于执行任务的函数,同步不开,异步才能开。
-开几条线程,取决于队列,串行开一条,并发可以开多条(异步)。
串行并发是根据任务来的
同步异步是根据线程来说的
串行同步:是我们一个一个依次去队列中拿任务,由主线程依次执行任务
串行异步:是我们一个一个依次去队列中拿任务,去线程池拿一条子线程依次执行任务
并行同步:是我们依次去队列中拿多个任务,交给一条线程去顺序执行
并行异步:是我们依次去队列中拿多个任务,再去线程池拿多个子线程去执行任务
串行队列,同步任务:不会开启线程,会顺序执行
//MARK:串行队列,同步任务
/**
不会开启线程,会顺序执行
*/
-(void)gcdDemo1{
//1.队列 - 串行
/**
1.队列名称:
2.队列属性:DISPATCH_QUEUE_SERIAL 标示串行
*/
dispatch_queue_t q = dispatch_queue_create("WT_queue", NULL);
//2.同步执行任务
dispatch_sync(q, ^{
NSLog(@"%@",[NSThread currentThread]);
});
//执行结果: 2018-05-04 10:45:43.324464+0800 002-GCD串行队列[1426:71131] {number = 1, name = main}在主队列中执行
}
串行队列,异步任务
//MARK:串行队列,异步任务
-(void)gcdDemo2{
//1.队列 - 串行
dispatch_queue_t q = dispatch_queue_create("WT_queue", NULL);
//2.异步执行任务
for (int i=0; i<10; i++) {
NSLog(@"%d-----------",i);//在主线程中,占用主线程资源,执行完毕后才能打印come here
dispatch_async(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}//只开一条线程
NSLog(@"come here");//它在主线程中,与子线程同时执行
}
并发队列,同步步执行
//MARK:- 并发队列,同步步执行
-(void)gcdDemo4{
/**
问题:会开几条线程?会顺序执行吗? come here的位置?
答案:不会,顺序执行,come here在最后打印
*/
//1.队列 - 并发 DISPATCH_QUEUE_CONCURRENT
dispatch_queue_t q = dispatch_queue_create("WT_queue", DISPATCH_QUEUE_CONCURRENT);
//2.同步执行任务
for (int i=0; i<10; i++) {
dispatch_sync(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}
NSLog(@"come here");
}
并发队列,异步执行
//MARK:- 并发队列,异步执行
-(void)gcdDemo3{
/**
问题:会开几条线程?会顺序执行吗? come here的位置?
答案:会开多条线程,不一定会顺序执行,come here在主线程中,与子线程同时开始
*/
//1.队列 - 并发 DISPATCH_QUEUE_CONCURRENT
dispatch_queue_t q = dispatch_queue_create("WT_queue", DISPATCH_QUEUE_CONCURRENT);
//2.异步执行任务
for (int i=0; i<10; i++) {
dispatch_async(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}
NSLog(@"come here");
}
//MARK:- 并发队列,同步步执行
-(void)gcdDemo4{
/**
问题:会开几条线程?会顺序执行吗? come here的位置?
答案:不会,顺序执行,come here在最后打印
*/
//1.队列 - 并发 DISPATCH_QUEUE_CONCURRENT
dispatch_queue_t q = dispatch_queue_create("WT_queue", DISPATCH_QUEUE_CONCURRENT);
//2.同步执行任务
for (int i=0; i<10; i++) {
dispatch_sync(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}
NSLog(@"come here");
}
在开发中,通常会将耗时操作放后台执行,有的时候,有些任务彼此有“依赖”关系
例子:登录,支付,下载(网络相关的全部放在子线程中执行)
利用同步任务,能够做到任务依赖关系,前一个任务是同步任务,它不执行完,队列就不会调度后面的任务
//MARK - 同步任务作用!
-(void)gcdDemo5{
dispatch_queue_t loginQueue = dispatch_queue_create("WT_queue", DISPATCH_QUEUE_CONCURRENT);
//1.用户登录
dispatch_sync(loginQueue, ^{
NSLog(@"用户登录 %@",[NSThread currentThread]);
});
for (int i=0; i<10; i++) {
NSLog(@"%d",i);
}
//2.支付
dispatch_async(loginQueue, ^{
NSLog(@"支付 %@",[NSThread currentThread]);
});
//3.下载
dispatch_async(loginQueue, ^{
NSLog(@"下载 %@",[NSThread currentThread]);
});
NSLog(@"come here");
}
可以让队列调度多个任务前,指定一个同步任务。让所有的异步任务,等待同步任务执行完成,这就是依赖关系
- 同步任务,会造成一个死锁,锁住此线程
#pragma mark -<同步任务>
//MARK: - 增强版同步任务
-(void)gcdDemo6{
//队列
dispatch_queue_t q =dispatch_queue_create("WT_queue", DISPATCH_QUEUE_CONCURRENT);
//任务
void (^task)(void)=^{
dispatch_async(q, ^{
for (int i=0; i<10; i++) {
NSLog(@"%d %@",i,[NSThread currentThread]);
}
});
//1.用户登录
dispatch_sync(q , ^{
NSLog(@"用户登录 %@",[NSThread currentThread]);
});
//2.支付
dispatch_async(q , ^{
NSLog(@"支付 %@",[NSThread currentThread]);
});
//3.下载
dispatch_async(q , ^{
NSLog(@"下载 %@",[NSThread currentThread]);
});
};
dispatch_async(q, task);
}
参数
1.涉及到系统适配
iOS 8 服务质量
QOS_CLASS_USER_INTERACTIVE //用户交互(希望线程快速被执行,不要用耗时的操作)
QOS_CLASS_USER_INITIATED //用户需要的(同样不要使用耗时操作)
QOS_CLASS_DEFAULT //默认的(给系统来重置队列的)
QOS_CLASS_UTILITY //使用工具(用来做耗时操作)
QOS_CLASS_BACKGROUND //后台
QOS_CLASS_UNSPECIFIED //没有指定优先级
iOS 7 调度的优先级
- DISPATCH_QUEUE_PRIORITY_HIGH 2 //高优先级
- DISPATCH_QUEUE_PRIORITY_DEFAULT 0 //默认优先级
- DISPATCH_QUEUE_PRIORITY_LOW (-2) //低优先级
- DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN //后台优先级
提示:不管是优先级还是服务质量,尤其不要选择BACKGROUND。如果选择线程执行会慢到令人发指!
2.为未来使用的一个保留,现在始终给0
在老项目中,一般还是没有淘汰iOS 7,没法使用服务质量
//MARK: 全局队列
-(void)gcdDemo7{
//全局队列(本质上是并发队列)
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
for (int i=0; i<10; i++) {
dispatch_async(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}
NSLog(@"come here");
}
全局队列 & 并发队列 区别
1> 名称,并发队列取名字,适合于企业开发跟踪错误
2> release,在MRC 并发队列 需要使用的
dispatch_release(q);//ARC情况下不需要release!
全局队列 & 串行队列
全局队列:并发,能够调度多个线程,执行效率高
-费电
串行队列:一个一个执行,执行效率低
-省电
判断依据:用户上网方式
-WIFI:可以多开线程
-流量:尽量少开线程