IOS线程池

时间:2016-08-07 08:03:14

标签: ios grand-central-dispatch

我有这个方法

-(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
        });
    });
    }

似乎调用者有时会因信号量障碍而被阻止。

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

由于

1 个答案:

答案 0 :(得分:3)

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

但是,您不希望将等待信号量转移到发送到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”是同步的)是使用NSOperationQueuemaxConcurrentOperationCount,它控制你的并发度。例如:

@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子类并不难,但有一些与此相关的细节。请参阅并发编程指南中的Configuring Operations for Concurrent Execution