上一讲我们谈到可以使用GCD调度组来实现异步处理完成后最后回到某个线程后集中处理(多接口异步请求.回到主线程刷新UI).戳:GCD调度组(dispatch_group)
这一讲我们来谈一个也能实现该需求的GCD信号量(Semaphores)
主要就是下面几个东西
// dispatch_semaphore_t
// dispatch_semaphore_create(<#long value#>)
// dispatch_semaphore_wait(<#dispatch_semaphore_t _Nonnull dsema#>, <#dispatch_time_t timeout#>)
// dispatch_semaphore_signal(<#dispatch_semaphore_t _Nonnull dsema#>)
dispatch_semaphore_t类似于dispatch_group_t这种东西就行.创建一个信号量就返回这个东西
dispatch_semaphore_create(<#long value#>)传入一个long类型数据.返回一个dispatch_semaphore_t.但是这个long类型的数据不能小于0,小于0的话会返回NULL.
// dispatch_semaphore_wait(<#dispatch_semaphore_t _Nonnull dsema#>, <#dispatch_time_t timeout#>)
这个先后顺序并不好描述.因为从代码上下结构来看的话.肯定是先写的提高信号量,然而在执行顺序上来说的话那就是降低信号量在前.
// dispatch_semaphore_signal(<#dispatch_semaphore_t _Nonnull dsema#>)
提高信号量可以让与之成对的wait失效.然后继续往下执行.
他有一个long类型的返回值,当没有wait的时候就会返回0.
注意:信号量和调度组不一样,需要先降低信号量,然后再提高.如果不成对出现可能会出现EXC_BAD_INSTRUCTION
错误,如果先降低信号量(wait)那么就可能导致代码卡死
/// 测试 GCD Semaphores
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"1");
dispatch_semaphore_signal(semaphore);
});
NSLog(@"5");
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"6");
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2");
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"3");
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"4");
输出结果的话是
516234
对于多线程有关的东西的话,还是得多次测试才能得出正确结论
加个延时测试一下
/// 测试 GCD Semaphores
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"1");
dispatch_semaphore_signal(semaphore);
});
NSLog(@"5");
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"6");
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"2");
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"3");
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"4");
输出结果还是5.1.6.2.3.4
那么就是.一直顺序执行.如果碰到了dispatch_semaphore_wait.他就会等到接收到signal信号量才会往下走.或者是等到wait的第二个参数(最大等待时间)达到(也算是收到了一个信号量吧).所以必须得在wait之前写下异步任务并且一定能发送出singal信号,或者有最大等待时间.不然会卡死.(直接wait的话线程阻塞.下面不会走.异步任务开在下面等于没开),
GCD的semaphore比较适合用于多个任务需要按某种顺序执行
/// 测试 GCD Semaphores
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"1");
long longValue = dispatch_semaphore_signal(semaphore);
NSLog(@"1.longValue:%ld" ,longValue);
});
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"2");
long longValue = dispatch_semaphore_signal(semaphore);
NSLog(@"2.longValue:%ld" ,longValue);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"3");
long longValue = dispatch_semaphore_signal(semaphore);
NSLog(@"3.longValue:%ld" ,longValue);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"4");
如果是上面这种的话,1和2的打印顺序就不一定了.所以说GCD Semaphores很适合用于定制任务执行顺序.