gpt4 book ai didi

ios - 为什么 NSOperationQueue.mainQueue.maxConcurrentOperationCount 设置为 1

转载 作者:行者123 更新时间:2023-12-01 18:38:08 25 4
gpt4 key购买 nike

这个问题的原因是因为对 this question 的 react 。 .

我意识到对问题的理解并不完全存在,以及首先提出问题的原因。所以我试图将另一个问题的原因归结为这个问题的核心。

首先是一个小前言,以及一些历史,我知道 NSOperation(Queue) 在 GCD 之前就已经存在,并且它们是在调度队列之前使用线程实现的。

接下来你需要了解的是,默认情况下,这意味着在操作或操作队列上不使用“等待”方法(只是标准的“addOperation:”),NSOperation 的主要方法在 NSOperationQueue 的底层队列上执行异步 (例如 dispatch_async())。

总结一下我的前言,我质疑在这个时代将 NSOperationQueue.mainQueue.maxConcurrentOperationCount 设置为 1 的目的,因为底层队列实际上是主要的 GCD 串行队列(例如 dispatch_get_main_queue() 的返回)。

如果 NSOperationQueue.mainQueue 已经连续执行了它的操作的主要方法,为什么还要担心 maxConcurrentOperationCount 呢?

要查看将其设置为 1 的问题,请参阅引用问题中的示例。

最佳答案

将其设置为 1 是因为没有理由将其设置为其他任何值,并且出于我能想到的至少三个原因,将其设置为 1 可能会稍微好一些。

原因一

因为NSOperationQueue.mainQueueunderlyingQueuedispatch_get_main_queue() ,是串行的,NSOperationQueue.mainQueue实际上是串行的(即使它的 maxConcurrentOperationCount 大于 1,它一次也不能运行超过一个 block )。

我们可以通过创建自己的 NSOperationQueue 来检查这一点。 ,将串行队列放入其underlyingQueue目标链,并设置其maxConcurrentOperationCount为大量。

使用 macOS > Cocoa App 模板和语言 Objective-C 在 Xcode 中创建一个新项目。替换 AppDelegate用这个实现:

@implementation AppDelegate {
dispatch_queue_t concurrentQueue;
dispatch_queue_t serialQueue;
NSOperationQueue *operationQueue;
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
concurrentQueue = dispatch_queue_create("q", DISPATCH_QUEUE_CONCURRENT);
serialQueue = dispatch_queue_create("q2", nil);
operationQueue = [[NSOperationQueue alloc] init];

// concurrent queue targeting serial queue
//dispatch_set_target_queue(concurrentQueue, serialQueue);
//operationQueue.underlyingQueue = concurrentQueue;

// serial queue targeting concurrent queue
dispatch_set_target_queue(serialQueue, concurrentQueue);
operationQueue.underlyingQueue = serialQueue;

operationQueue.maxConcurrentOperationCount = 100;

for (int i = 0; i < 100; ++i) {
NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"operation %d starting", i);
sleep(3);
NSLog(@"operation %d ending", i);
}];
[operationQueue addOperation:operation];
}
}

@end

如果你运行它,你会看到操作 1 直到操作 0 结束才开始,即使我设置了 operationQueue.maxConcurrentOperationCount。到 100。发生这种情况是因为 operationQueue.underlyingQueue 的目标链中有一个串行队列.因此 operationQueue实际上是串行的,即使它的 maxConcurrentOperationCount不是 1。

您可以使用代码来尝试更改目标链的结构。您会发现,如果该链中的任何位置都有串行队列,则一次只能运行一个操作。

但是如果你设置 operationQueue.underlyingQueue = concurrentQueue ,然后执行 不是 设置 concurrentQueue的目标为 serialQueue ,然后您会看到 64 个操作同时运行。对于 operationQueue要同时运行操作,整个目标链从其 underlyingQueue 开始必须是并发的。

由于主队列总是串行的, NSOperationQueue.mainQueue实际上总是连续的。

事实上,如果你设置 NSOperationQueue.mainQueue.maxConcurrentOperationCount除了 1 之外的任何东西,它都没有效果。如果您打印 NSOperationQueue.mainQueue.maxConcurrentOperationCount在尝试更改它之后,您会发现它仍然是 1。我认为如果尝试更改它会引发断言会更好。默默地忽略改变它的尝试更有可能导致困惑。

原因 2
NSOperationQueue最多提交 maxConcurrentOperationCount block 到它的 underlyingQueue同时地。由于 mainQueue.underlyingQueue是串行的,一次只能运行其中一个 block 。一旦提交了这些 block ,使用 -[NSOperation cancel] 可能为时已晚。消息取消相应的操作。我不知道;这是一个我还没有完全探索的实现细节。无论如何,如果为时已晚,那将是不幸的,因为这可能会导致时间和电池电量的浪费。

原因 3

如原因 2 所述, NSOperationQueue最多提交 maxConcurrentOperationCount block 到它的 underlyingQueue同时地。由于 mainQueue.underlyingQueue是串行的,一次只能执行其中一个 block 。其他 block 和任何其他资源 dispatch_queue_t用来追踪他们,必须无所事事地坐着,等待轮到他们跑。这是对资源的浪费。不是很大的浪费,但还是很浪费。如果 mainQueue.maxConcurrentOperationCount设置为 1,它只会向其 underlyingQueue 提交单个 block 一次,从而防止 GCD 无用地分配资源。

关于ios - 为什么 NSOperationQueue.mainQueue.maxConcurrentOperationCount 设置为 1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48087427/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com