GCD提供了信号semaphore来控制线程并发数,提供一下三个函数
dispatch_semaphore_create(<#long value#>) // 创建信号semaphore,value参数为任务并发同时执行时线程最大并发数
dispatch_semaphore_wait(<#dispatch_semaphore_t _Nonnull dsema#>, <#dispatch_time_t timeout#>) // 信号阻塞,信号发送后->判断是否有空闲的计数可用,如果有可用计数执行后面的任务,如果没有可用计数就让当前线程阻塞
dispatch_semaphore_signal(<#dispatch_semaphore_t _Nonnull dsema#>) // 信号发送,信号发送后->通知有空闲的计数可用,其他阻塞的任务就可以执行
dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i=0; i<20; i++) { // for 20次,每次创建一个线程执行任务,当线程任务达到2个后,创建任务就会被阻塞,至到有任务完成并signal后,wait等待线程才会解除阻塞,继续被执行
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_group_async(group, queue, ^{
NSLog(@"%zd ---%@",i,[NSThread currentThread]);
[NSThread sleepForTimeInterval:0.2];
dispatch_semaphore_signal(semaphore);
});
}
dispatch_group_wait(group, 4); // group任务等待4秒,如果group所有任务任务4秒还未执行完成,执行下面任务
dispatch_group_notify(group, queue, ^{
NSLog(@"dispatch_group_notify"); // group内任务全部执行完毕,通知回调
});
NSLog(@"semaphore end...");
2017-09-02 20:31:53.611 GCD测试[16021:328482] 0 ---{number = 7, name = (null)}
2017-09-02 20:31:53.611 GCD测试[16021:329153] 1 ---{number = 10, name = (null)}
2017-09-02 20:31:53.885 GCD测试[16021:328482] 2 ---{number = 7, name = (null)}
2017-09-02 20:31:53.885 GCD测试[16021:329153] 3 ---{number = 10, name = (null)}
2017-09-02 20:31:54.152 GCD测试[16021:328482] 4 ---{number = 7, name = (null)}
2017-09-02 20:31:54.152 GCD测试[16021:329153] 5 ---{number = 10, name = (null)}
2017-09-02 20:31:54.400 GCD测试[16021:329153] 6 ---{number = 10, name = (null)}
2017-09-02 20:31:54.400 GCD测试[16021:328482] 7 ---{number = 7, name = (null)}
2017-09-02 20:31:54.601 GCD测试[16021:329153] 8 ---{number = 10, name = (null)}
2017-09-02 20:31:54.601 GCD测试[16021:328482] 9 ---{number = 7, name = (null)}
2017-09-02 20:31:54.801 GCD测试[16021:329153] 10 ---{number = 10, name = (null)}
2017-09-02 20:31:54.801 GCD测试[16021:328482] 11 ---{number = 7, name = (null)}
2017-09-02 20:31:55.069 GCD测试[16021:329153] 13 ---{number = 10, name = (null)}
2017-09-02 20:31:55.069 GCD测试[16021:328482] 12 ---{number = 7, name = (null)}
2017-09-02 20:31:55.270 GCD测试[16021:328482] 14 ---{number = 7, name = (null)}
2017-09-02 20:31:55.270 GCD测试[16021:329153] 15 ---{number = 10, name = (null)}
2017-09-02 20:31:55.470 GCD测试[16021:329153] 17 ---{number = 10, name = (null)}
2017-09-02 20:31:55.470 GCD测试[16021:328482] 16 ---{number = 7, name = (null)}
2017-09-02 20:31:55.711 GCD测试[16021:328215] semaphore end...
2017-09-02 20:31:55.711 GCD测试[16021:328482] 18 ---{number = 7, name = (null)}
2017-09-02 20:31:55.711 GCD测试[16021:329153] 19 ---{number = 10, name = (null)}
2017-09-02 20:31:55.912 GCD测试[16021:329153] dispatch_group_notify
经测试信号量设置为2,但是任务开启的任务线程有时可能为3个,这个不是说信号量不起作用,3表示并发线程2个,但是线程使用完后,下次2个同时并发时可能会开启新的线程,也有可能直接使用上次并发完的线程
示例:
__block BOOL isok = NO;
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
EventEngine *engine = [[EventEngine alloc] init];
[engine engineCompletion:^(BOOL isOpen) {
isok = isOpen;
dispatch_semaphore_signal(sema);
} onError:^(int errorCode, NSString *errorMessage) {
isok = NO;
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
// 等待engine有结果后才解除阻塞
// do other task