我正在从数据库异步获取数据。有什么办法可以将并发请求限制为一个数字,但仍然执行其余的请求?
我看到一篇使用 NSOperation 和 NSOperationQueue 的帖子,但这对我来说太复杂了。还有其他方法吗?GCD能做到吗?
我正在从数据库异步获取数据。有什么办法可以将并发请求限制为一个数字,但仍然执行其余的请求?
我看到一篇使用 NSOperation 和 NSOperationQueue 的帖子,但这对我来说太复杂了。还有其他方法吗?GCD能做到吗?
像这样的东西:
...
//only make one of these obviously :) remaking it each time you dispatch_async wouldn't limit anything
dispatch_semaphore_t concurrencyLimitingSemaphore = dispatch_semaphore_create(limit);
...
//do this part once per task, for example in a loop
dispatch_semaphore_wait(concurrencyLimitingSemaphore, DISPATCH_TIME_FOREVER);
dispatch_async(someConcurrentQueue, ^{
/* work goes here */
dispatch_semaphore_signal(concurrencyLimitingSemaphore);
}
对于同步任务的有限并发执行,我建议使用此解决方案:
func dispatch_async_batch(tasks: [() -> ()], limit: Int, completion: (() -> ())?) {
if tasks.count > 0 || completion != nil {
let q = dispatch_queue_create("dispatch_async_batch", DISPATCH_QUEUE_CONCURRENT);
let sema = dispatch_semaphore_create(limit);
dispatch_async(q, {
for task in tasks {
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)
dispatch_async(q, {
task()
dispatch_semaphore_signal(sema)
})
}
if let completion = completion {
dispatch_barrier_async(q, completion)
}
})
}
}
这种方法的开销很小:除了当前正在执行的任务之外,只有一个额外的任务被放在队列中(即一个额外的线程)。当你有大量的任务时,它特别好。
这个gist是一个随时可用的演示,只需将代码放入 Playground 即可。
简单的方法是设置 n 个串行队列
struct dataCalls {
let n:Int
func fetchIt(){
print ("Done",n)
}
init(n:Int){
self.n=n
}
}
var dataCallsArray: [dataCalls]=[]
var qArray:[dispatch_queue_t] = []
let n = 5
for i in 1...50 {
dataCallsArray.append(dataCalls(n:i))
}
for _ in 1...n {
qArray.append(dispatch_queue_create(nil, nil))
}
var i = 0
for data in dataCallsArray {
dispatch_async(qArray[i%n], {() -> Void in data.fetchIt()})
i++
}