IOS线程池

我有这个方法

-(void)addObjectToProcess(NSObject*)object; 

我希望这个方法将对象添加到进程队列,该队列可以并行处理多达4个对象。

我已经创建了自己的dispatch_queue和semhphore

  _concurrentQueue = dispatch_queue_create([queue_id UTF8String],DISPATCH_QUEUE_CONCURRENT); _processSema = dispatch_semaphore_create(4); 

并且该方法的实现是:

 -(void)addObjectToProcess(NSObject*)object { dispatch_semaphore_wait(self.processSema, DISPATCH_TIME_FOREVER); __weak MyViewController* weakSelf = self; dispatch_async(self.concurrentQueue, ^{ // PROCESS........... // .................. dispatch_semaphore_signal(self.processSema); dispatch_async(dispatch_get_main_queue(), ^{ // call delegate from UI thread }); }); } 

似乎呼叫者有时会被信号屏障阻塞。

有没有其他/更容易的选择来实现我想在这里做什么?

谢谢

问题是你在任何调用addObjectToProcess线程上调用dispatch_semaphore_wait (可能是主线程)。 因此,如果您已经运行了四个任务,那么当您安排第五个进程时,它将在主线程上等待。

但是,您不希望将等待信号量移动到调度到self.concurrentQueue的块中,因为虽然这将成功地将“PROCESS”任务一次限制为四个,但您将为每个执行另一个工作线程其中一个积压的调度任务,并且这些工作线程数量有限。 当你耗尽这些时,你可能会对其他过程产生负面影响。

解决此问题的一种方法是创建除并发处理队列之外的串行调度队列,然后将此整个调度任务异步调度到此调度队列。 因此,您可以享受进程队列中的最大并发性,同时既不会阻塞主线程也不会使用工作线程来执行积压任务。 例如:

 @property (nonatomic, strong) dispatch_queue_t schedulingQueue; 

 self.schedulingQueue = dispatch_queue_create("com.domain.scheduler", 0); 

 - (void)addObjectToProcess(NSObject*)object { dispatch_async(self.schedulingQueue, ^{ dispatch_semaphore_wait(self.processSema, DISPATCH_TIME_FOREVER); typeof(self) __weak weakSelf = self; dispatch_async(self.concurrentQueue, ^{ // PROCESS........... // .................. typeof(self) __strong strongSelf = weakSelf; if (strongSelf) { dispatch_semaphore_signal(strongSelf.processSema); dispatch_async(dispatch_get_main_queue(), ^{ // call delegate from UI thread }); } }); }); } 

另一个好的方法(特别是如果“PROCESS”是同步的)是使用具有maxConcurrentOperationCount ,它控制你的并发度。 例如:

 @property (nonatomic, strong) NSOperationQueue *processQueue; 

并初始化它:

 self.processQueue = [[NSOperationQueue alloc] init]; self.processQueue.maxConcurrentOperationCount = 4; 

接着:

 - (void)addObjectToProcess(NSObject*)object { [self.processQueue addOperationWithBlock:^{ // PROCESS........... // .................. dispatch_async(dispatch_get_main_queue(), ^{ // call delegate from UI thread }); }]; } 

唯一的技巧是“PROCESS”本身是异步的。 如果你这样做,那么你不能只使用addOperationWithBlock ,而是必须编写自己的自定义,异步NSOperation子类,然后使用addOperationNSOperationQueue 。 编写异步NSOperation子类并不难,但是有一些与之相关的细节。 请参阅“ 并发编程指南”中的“为并发执行配置操作 ”。