NSOperationQueue对象有一个属性 maxConcurrentOperationCount,可以设置当前队列任务同时并发的最大个数,也就是同时执行任务的最大个数。比如我们下载很多电影,每个下载中的电影都是一个下载任务,如果设置maxConcurrentOperationCount=5,则表示当前最大只能同时下载5部电影。
GCD是一套C语言的API,所以没有什么属性控制最大并发量。如果我们用的是GCD编程,需要现实这样的需求应该怎么办?那可以用dispatch_semaphore_t(信号量)来实现。
信号量是一个整形值并且具有一个初始计数值,并且支持两个操作:信号通知和等待。当一个信号量被信号通知,其计数会被增加。当一个线程在一个信号量上等待时,线程会被阻塞(如果有必要的话),直至计数器大于零,然后线程会减少这个计数。
在GCD中有三个函数是semaphore的操作,分别是:
- dispatch_semaphore_create 创建一个semaphore
- dispatch_semaphore_signal 发送一个信号
- dispatch_semaphore_wait 等待信号
简单的介绍一下这三个函数,第一个函数有一个整形的参数,我们可以理解为信号的总量,dispatch_semaphore_signal是发送一个信号,自然会让信号总量加1,dispatch_semaphore_wait等待信号,当信号总量少于0的时候就会一直等待,否则就可以正常的执行,并让信号总量-1,根据这样的原理,我们便可以快速的创建一个并发控制来同步任务和有限资源访问控制。
- (void)gcdSemaphore
{
dispatch_group_t group = dispatch_group_create();
dispatch_semaphore_t semaphore = dispatch_semaphore_create(5);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 20; i++)
{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_group_async(group, queue, ^{
NSLog(@"时间在:%@进行第:%d个输出 %@ \n",[[NSDate date] description],i,[NSThread currentThread]);
sleep(1);
dispatch_semaphore_signal(semaphore);
});
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
}
image.png
信号量的一种形象比喻
-
停车场剩余4个车位,那么即使同时来了四辆车也能停的下。如果此时来了五辆车,那么就有一辆需要等待。
-
信号量的值就相当于剩余车位的数目,
dispatch_semaphore_wait函数就相当于来了一辆车,dispatch_semaphore_signal就相当于走了一辆车。停车位的剩余数目在初始化的时候就已经指明了dispatch_semaphore_create(long value)。 -
调用一次dispatch_semaphore_signal,剩余的车位就增加一个;调用一次dispatch_semaphore_wait剩余车位就减少一个;
-
当剩余车位为0时,再来车(即调用dispatch_semaphore_wait)就只能等待。有可能同时有几辆车等待一个停车位。有些车主没有耐心,给自己设定了一段等待时间,这段时间内等不到停车位就走了,如果等到了就开进去停车。而有些车主就想把车停在这,所以就一直等下去。
网友评论