本文介绍了iOS线程池的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有此方法

-(void)addObjectToProcess(NSObject*)object;

,我希望此方法将对象添加到处理队列中,该队列最多可以并行处理4个对象.

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

我创建了自己的dispatch_queue和semhphore

i've created my own dispatch_queue and 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
        });
    });
    }

似乎呼叫者有时会因信号量障碍而被阻止.

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 ?

谢谢

推荐答案

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

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.

但是,您不必只是将等待信号量移到分派给self.concurrentQueue的块中,因为尽管这样可以一次成功地将"PROCESS"任务限制为四个,但是您将消耗另一个工作程序这些积压的已分派任务中的每个任务的最大线程数,并且这些工作线程数是有限的.而且,当您用尽这些资源时,可能会对其他流程产生不利影响.

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;

还有

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

另一种好的方法(尤其是在过程"是同步的情况下)是使用具有maxConcurrentOperationCountNSOperationQueue,它可以为您控制并发程度.例如:

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;

并对其进行初始化:

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

唯一的窍门是过程"本身是异步的.如果这样做,则不仅可以使用addOperationWithBlock,还必须编写自己的自定义异步NSOperation子类,然后对NSOperationQueue使用addOperation.编写异步NSOperation子类并不难,但是有一些与此相关的小细节.参见并发编程指南》中的"nofollow>配置并发执行操作.

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.

这篇关于iOS线程池的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 06:11