當我們在處理多線程的時候,如果想控制并發線程的數量,我們會使用NSOperationQueue
的maxConcurrentOperationCount
來進行控制,所以遇到此類問題,我們一般會使用NSOperation+ NSOperationQueue來解決。
我們也可以使用GCD來解決這個問題,就是配合dispatch_semaphore來使用。
dispatch_semaphore就是信號量,在以前的Linux開發中就已經用過。信號量是一個整形值,在初始化的時候分配一個初始值,支持兩個操作信號通知
和等待
。
等待
// 返回0:表示正常。返回非0:表示等待時間超時
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
信號通知
long dispatch_semaphore_signal(dispatch_semaphore_t dsema);
創建信號量
// 值得注意的是,這里的傳入的參數value必須大于或等于0,否則dispatch_semaphore_create會返回NULL
dispatch_semaphore_t dispatch_semaphore_create(long value);
- 當一個信號量被通知
dispatch_semaphore_signal
,計數會加1;- 如果一個線程等待一個信號量
dispatch_semaphore_wait
,線程會被阻塞,直到計數器>0,此時開始運行,并且對信號量減1。
這樣我們就可以根據 初始值 ,來控制可以有多少個并發的線程在運行。關于信號量,可以用停車位來比喻,如果停車場有5個停車位,都停滿了,如果此時來了第6輛車,就需要等待,信號量的值就相當于剩余的車位的數量
。dispatch_semaphore_wait函數就相當于來了一輛車,dispatch_semaphore_signal就相當于走了一輛車。
dispatch_semaphore_wait中的參數timeout表示超時時間,如果等待期間沒有獲取到信號量或者信號量的值一直為0,那么等到timeout時,其所處線程自動執行其后語句??扇≈禐椋?code>DISPATCH_TIME_NOW和 DISPATCH_TIME_FOREVER
,我們也可以自己設置一個dispatch_time_t的時間值,表示超時時間為這個時間之后。
- DISPATCH_TIME_NOW:超時時間為0,表示忽略信號量,直接運行
- ** DISPATCH_TIME_FOREVER**:超時時間為永遠,表示會一直等待信號量為正數,才會繼續運行
來看一個具體的例子:
信號量的初始值設置為:1,即最多只能又一個線程在run,可以驗證一下運行結果,除去最開始的三個,后面的是每三秒打印一個,并且保證運行的順序按照添加的順序。
如果把創建信號量的值設置為4,即最多可以有4個線程同時運行,來看一下運行結果,是每三秒同時打印四個,且順序不能保證。