线程就像是在程序运行时又另开一条道路去做一些耗时的操作,不能让所有的操作都堵在主线程那条路上,这样就像北京的堵车一样,体验非常不好。队列就相当于你修的单行路还是多行路
1.dispatch_queue_t
这个类就像是创建的道路的样式
通过这个方法来创建一条新的道路,这个方法需要传2个参数,第一个参数是为队列添加一个唯一标识,第二个参数是这个队列的属性:
DISPATCH_QUEUE_SERIAL(串行(单行道)for Null也是串行)
DISPATCH_QUEUE_CONCURRENT(并行(多行道))
dispatch_queue_create(const char *_Nullable label,
dispatch_queue_attr_t _Nullable attr);
串行就是所有加入队列的操作就是依次执行,看代码效果吧:
//串行队列
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
//加入俩个异步操作
dispatch_async(queue, ^{
for(int i=0;i<5;i++ ){
NSLog(@" 1当前线程 %@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for(int i=0;i<5;i++ ){
NSLog(@" 2当前线程 %@",[NSThread currentThread]);
}
});
看下结果,可以看出来是依次执行的先把上一个操作执行完,并且不是在主线程中进行的
改下代码
//把之前的方法参数改为并行属性
dispatch_queue_t queue1 = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
可以看到结果是一起执行,执行的线程编号为3和4俩个线程里,也不是在主线程中进行
有可能常见的有一个这个, 这是一个系统全局并行队列
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
2.dispatch_group_t
就是一个队列组,把队列给套起来的感觉,线程里面任务结束会发出一个消息
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group, queue, ^{
for(int i=0;i<10;i++ ){
NSLog(@" 0当前线程 %@",[NSThread currentThread]);
}
});
dispatch_group_async(group, queue, ^{
for(int i=0;i<10;i++ ){
NSLog(@" 1当前线程 %@",[NSThread currentThread]);
}
});
dispatch_group_async(group, queue, ^{
for(int i=0;i<10;i++ ){
NSLog(@" 2当前线程 %@",[NSThread currentThread]);
}
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"完成");
});
效果:
这样我们可以在完成异步操作的时候做一些想做的事情。
但实际的操作本身网络请求就是异步的,所以我们要配合下面的方法
//加入组
dispatch_group_enter(group);
//离开组
dispatch_group_leave(group);
//修改后代码
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group, queue, ^{
dispatch_group_enter(group);
//延迟调用模拟网络请求
dispatch_time_t time=dispatch_time(DISPATCH_TIME_NOW, 5*NSEC_PER_SEC);
dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"操作一完成");
dispatch_group_leave(group);
});
});
dispatch_group_async(group, queue, ^{
dispatch_group_enter(group);
//延迟调用模拟网络请求
dispatch_time_t time=dispatch_time(DISPATCH_TIME_NOW, 10*NSEC_PER_SEC);
dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"操作二完成");
dispatch_group_leave(group);
});
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"全部完成");
});
可以看出leave和enter得对应上,如果只enter不leave 最后的消息一直不会走
上面这个操作可以很好处理一个界面多个网络请求的问题,当所有的网络请求都结束时会得到通知并进行操作就可以了