关于GCD的个人理解
序言
这是最近整理出来的关于自己的一些想法
前提
首先要了解一些比较常用的英文术语:
dispatch 调度,派遣
retain 保持
in parallel 并行
in serial 串行,连续的
Concurrent 同时发生的
priority 优先级,优先权(pal o ri ti)
dispatch_suspend 调度暂停
dispatch_resume 调度恢复
dispatch_set_context 调度设置环(背/ 语)境,调度设置上下文
queue 队列,用于存放任务。一共有两种队列, 串行队列 和 并行队列。
什么是GCD
目前大多iOS程序员用的一种多线程开发技术,是一个block,写起来简单粗暴,执行方式分为同步和异步,我一般用异步,因为同步会阻塞当前线程并等待 Block 中的任务执行完才会让当前线程继续执行下去。
大致分为了三类:
-
全局的并行的queue ,
eg:dispatch_queue_t a = dispatch_get_global_queue(优先级参数,0);
-
主线程的串行的queue,
eg:dispatch_queue_t a = dispatch_get_main_queue();
-
自定义的queue ,
eg:dispatch_queue_t a = dispatch_creat_queue("唯一标识”,串行还是并行参数);
关于调用
异步全局线程执行
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
});
第一个参数:
我们用priority指定队列的优先级,参数有
DISPATCH_QUEUE_PRIORITY_HIGH
DISPATCH_QUEUE_PRIORITY_DEFAULT
DISPATCH_QUEUE_PRIORITY_LOW
优先级由高到低,如果我们同时新建多个global_queue而又想按我们的顺序去执行,可以指定优先级,否则无法判定执行顺序
第二个参数:
作为保留字段备用(一般为0)。
异步主线程执行
dispatch_async(dispatch_get_main_queue(), ^{
});
需要注意的是主线程是一个特殊的串行队列,我们的UI刷新都要在这里操作,耗时的任务不能放在这里,否则会引发阻塞。
异步自建线程执行
dispatch_async(dispatch_queue_create("aaa", DISPATCH_QUEUE_SERIAL), ^{
});
第一个参数:aaa是这个线程的唯一标识,可以自行命名
第二个参数:标示改线程是串行还是并行执行,DISPATCH_QUEUE_SERIAL
标示串行,并行用DISPATCH_QUEUE_CONCURRENT
关于串行和并行的区别
我们试着执行一个自建的串行队列,然后逐步执行任务1,2,3
每个任务执行完等待3秒
dispatch_queue_t myQueue = dispatch_queue_create("123", DISPATCH_QUEUE_SERIAL);
dispatch_async(myQueue, ^{
NSLog(@"start task 1");
[NSThread sleepForTimeInterval:3];
NSLog(@"end task 1");
});
dispatch_async(myQueue, ^{
NSLog(@"start task 2");
[NSThread sleepForTimeInterval:3];
NSLog(@"end task 2");
});
dispatch_async(myQueue, ^{
NSLog(@"start task 3");
[NSThread sleepForTimeInterval:3];
NSLog(@"end task 3");
});
执行结果
这个执行说明任务是一个上一个结束才会执行下一个,如果参数改成DISPATCH_QUEUE_CONCURRENT,就会并发执行,无法判定先后,执行结果如下
关于group的概念
GCD另一个比较常用的方法就是dispatch_group_queue
,可以理解为把相关的任务归并到一个组内来执行,通过监听组内所有任务的执行情况来做相应处理
创建方法
dispatch_group_t group = dispatch_group_create();
异步执行group
dispatch_group_async(dispatch_group_create(), dispatch_queue_create("abc", DISPATCH_QUEUE_SERIAL), ^{
;
});
第一个参数:对应的 group,之后可以通过dispatch_group_wait或者dispatch_group_notify监听group内任务的执行情况
第二个参数:block任务执行的线程队列,group内不同任务的队列可以不同
第三个参数:执行任务的block
关于group对应的一些用法
参考文献:https://www.jianshu.com/p/6faea7ef35bc
dispatch_group_enter
用于添加对应任务组中的未执行完毕的任务数,执行一次,未执行完毕的任务数加1,当未执行完毕任务数为0的时候,才会使dispatch_group_wait
解除阻塞和dispatch_group_notify
的block执行
void dispatch_group_enter(dispatch_group_t group);
dispatch_group_leave
用于减少任务组中的未执行完毕的任务数,执行一次,未执行完毕的任务数减1,dispatch_group_enter
和dispatch_group_leave
要匹配,不然系统会认为group任务没有执行完毕
void dispatch_group_leave(dispatch_group_t group);
dispatch_group_wait
等待组任务完成,会阻塞当前线程,当任务组执行完毕时,才会解除阻塞当前线程
long dispatch_group_wait(dispatch_group_t group,
dispatch_time_t timeout);
group ——需要等待的任务组
timeout ——等待的超时时间(即等多久),单位为dispatch_time_t。如果设置为DISPATCH_TIME_FOREVER,则会一直等待(阻塞当前线程),直到任务组执行完毕
dispatch_group_notify
待任务组执行完毕时调用,不会阻塞当前线程
void dispatch_group_notify(dispatch_group_t group,
dispatch_queue_t queue,
dispatch_block_t block);
group ——需要监听的任务组
queue ——block任务执行的线程队列,和之前group执行的线程队列无关
block ——任务组执行完毕时需要执行的任务block