将其设置为 1 是因为没有理由将其设置为其他任何值,并且出于我能想到的至少三个原因,将其设置为 1 可能会稍微好一些。
原因一
因为NSOperationQueue.mainQueue
's underlyingQueue
isdispatch_get_main_queue()
是串行的,NSOperationQueue.mainQueue
实际上是串行的(它一次永远不能运行超过一个块,即使它maxConcurrentOperationCount
大于 1)。
我们可以通过创建自己的、在其目标链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
同时向其提交最多块underlyingQueue
。由于mainQueue.underlyingQueue
是串行的,因此一次只能运行其中一个块。-[NSOperation cancel]
一旦那些区块被提交,使用消息取消相应的操作可能已经来不及了。我不确定; 这是一个我还没有完全探索的实现细节。无论如何,如果为时已晚,那将是不幸的,因为这可能会导致时间和电池电量的浪费。
原因 3
如原因 2 所述,同时向其NSOperationQueue
提交最多块。由于是串行的,因此一次只能执行其中一个块。其他块以及用于跟踪它们的任何其他资源必须闲置,等待轮到它们运行。这是对资源的浪费。不是很大的浪费,但还是很浪费。如果设置为 1,它一次只会向它提交一个块,从而防止 GCD 无用地分配资源。maxConcurrentOperationCount
underlyingQueue
mainQueue.underlyingQueue
dispatch_queue_t
mainQueue.maxConcurrentOperationCount
underlyingQueue