- 在研究
GCD
前,先来一篇函数与队列
,这样,GCD
就更容易理解了
1. 概念篇
1.1. GCD中的函数
-
- 任务使用
block
封装
- 任务使用
-
- 任务的
block
没有参数也没有返回值
- 任务的
-
- 执行任务的函数
- 3.1. 异步
dispatch_async
不用等待当前语句执行完毕,就可以执行下一条语句
会开启线程执行
block
的任务异步是多线程的代名词
- 3.2. 同步
dispatch_sync
必须等待当前语句执行完毕,才会执行下一条语句
不会开启线程
在当前执行
block
的任务
1.2. 队列
-
- 关于队列,有一幅比较形象的图:
-
串行队列
分析:就是要排队,就一个通道:FIFO(先进先出)
-
并行队列
分析:假设在窗口买饭,有4个窗口,没准谁先买完
感觉换成吃的,比较好理解~~
1.3. 函数与队列的结合
-
-
同步函数串行队列
- 不会开启线程,在当前线程执行任务
- 任务串行执行,任务一个接着一个
- 会产生堵塞
-
-
-
同步函数并发队列
- 不会开启线程,在当前线程执行任务
- 任务一个接着一个
-
-
-
异步函数串行队列
- 开启一条新线程
- 任务一个接着一个
-
-
-
异步函数并发队列
- 开启线程,在当前线程执行任务
- 任务异步执行,没有顺序,和
CPU
调度有关
-
2. 应用
- 在函数和队列的运用,就通过面试题讲解(听说面试考量比较多)
2.1. 面试题1
- 写出下面程序输出
- (void)textDemo1{
dispatch_queue_t queue = dispatch_queue_create("question1", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"1");
dispatch_async(queue, ^{
NSLog(@"2");
dispatch_sync(queue, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
分析:
- 这个是个并行队列
- 无论是同步还是异步都是耗时的
- 所以先出来的是主队列的
1-5
- 在并行队列中是同步队列,所以依次执行
答案:1-5-2-3-4
2.2. 面试题2
- 写出下面程序输出
- (void)textDemo2{
// 同步队列
dispatch_queue_t queue = dispatch_queue_create("question2", NULL);
NSLog(@"1");
// 异步函数
dispatch_async(queue, ^{
NSLog(@"2");
// 同步
dispatch_sync(queue, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
分析
- 这个是串行队列:
#define DISPATCH_QUEUE_SERIAL NULL
- 先出来的是主队列的
1-5
- 然后输出
2
.- 之后大家就比较迷茫了。我画了个图:
块任务
添加3任务
,然后3任务
等待4任务
执行完,4任务
等待块任务
执行完,块任务
等待3任务
执行完- 这样就形成了
死锁
答案: 1-5-2-卡住
2.3. 面试题3
-
选择题:以下程序输出可能是()
A : 1230789
B : 1237890
C : 3120798
D : 2137890
- (void)textDemo3{
dispatch_queue_t queue = dispatch_queue_create("question3", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"1");
});
dispatch_async(queue, ^{
NSLog(@"2");
});
dispatch_sync(queue, ^{
NSLog(@"3");
});
NSLog(@"0");
dispatch_async(queue, ^{
NSLog(@"7");
});
dispatch_async(queue, ^{
NSLog(@"8");
});
dispatch_async(queue, ^{
NSLog(@"9");
});
}
分析:
- 这是一个
并行队列
,异步线程 1 2
和同步线程3
不能确定谁先执行完3任务
是同步线程
,所以,3
肯定在0
前面7-8-9任务
是异步线程
,所以没有顺序,但是肯定在0
之后
答案: AC