IOS thread pool

风流意气都作罢 提交于 2020-01-02 09:19:13

问题


I've got this method

-(void)addObjectToProcess(NSObject*)object;

and i want this method to add the object to process queue which can process up to 4 objects in parallel.

i've created my own dispatch_queue and semhphore

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

and the implementation of the method is:

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

it seems the caller sometimes gets blocked cause of the semaphore barrier.

is there any other/easier option to implement what i'm trying to make here ?

Thanks


回答1:


The problem is that you're calling dispatch_semaphore_wait on whatever thread you called addObjectToProcess on (presumably the main thread). Thus, if you already have four tasks running, when you schedule this fifth process, it will wait on the main thread.

You don't, though, just want to move the waiting for the semaphore into the block dispatched to self.concurrentQueue, because while that will successfully constrain the "PROCESS" tasks to four at a time, you will consume another worker thread for each one of these backlogged dispatched tasks, and there are a finite number of those worker threads. And when you exhaust those, you could adversely affect other processes.

One way to address this would be to create a serial scheduling queue in addition to your concurrent processing queue, and then dispatch this whole scheduling task asynchronously to this scheduling queue. Thus you enjoy the maximum concurrency on the process queue, while neither blocking the main thread nor using up worker threads for backlogged tasks. For example:

@property (nonatomic, strong) dispatch_queue_t schedulingQueue;

And

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

And

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

Another good approach (especially if the "PROCESS" is synchronous) is to use NSOperationQueue that has a maxConcurrentOperationCount, which controls the degree of concurrency for you. For example:

@property (nonatomic, strong) NSOperationQueue *processQueue;

And initialize it:

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

And then:

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

The only trick is if the "PROCESS", itself, is asynchronous. If you do that, then you can't just use addOperationWithBlock, but rather have to write your own custom, asynchronous NSOperation subclass, and then use addOperation to the NSOperationQueue. It's not hard to write asynchronous NSOperation subclass, but there are a few little details associated with that. See Configuring Operations for Concurrent Execution in the Concurrency Programming Guide.



来源:https://stackoverflow.com/questions/38812161/ios-thread-pool

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!