结论:setMaxConcurrentOperationCount 不能控制线程池中的线程数或线程数上限(或者说不是唯一因素)
摘自官方文档对 setMaxConcurrentOperationCoun 的说明 : affects only the operations that the current queue has executing at the same time. 翻译过来,就是影响同时执行的 operations 数,此处的 operations 是一个任务单位,使用者将子任务以 NSOperation 对象的形式添加。
这里的 NSOperation 可以理解成一个任务,但不能理解成这个任务只对应一个处理线程。
如: NSBlockOperation对象 是NSOperation类的一个子类, NSBlockOperation类有
+ (instancetype)blockOperationWithBlock:(void (^)(void))block;
初始化方法, 此方法可以以block的形式添加一个子任务, 另外他还有
- (void)addExecutionBlock:(void (^)(void))block;
的对象方法, 用来继续添加block形式的子任务.
而使用了NSBlockOperation对象作为任务 添加到 NSOperationQueue时, 每个任务则可能不止对应一个线程.
实例代码如:
NSMutableDictionary *dicMuThreads = [NSMutableDictionary dictionary];
NSLock *lock = [[NSLock alloc] init];
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
[lock lock];
NSThread *current = [NSThread currentThread];
NSString *strThread = [NSString stringWithFormat: @"%@",current];
[dicMuThreads setObject:@"a" forKey:strThread];
NSLog(@"a--%@",strThread);
[lock unlock];
}];
[op1 addExecutionBlock:^{
[lock lock];
NSThread *current = [NSThread currentThread];
NSString *strThread = [NSString stringWithFormat: @"%@",current];
[dicMuThreads setObject:@"a" forKey:strThread];
NSLog(@"a--%@",strThread);
[lock unlock];
}];
[op1 addExecutionBlock:^{
[lock lock];
NSThread *current = [NSThread currentThread];
NSString *strThread = [NSString stringWithFormat: @"%@",current];
[dicMuThreads setObject:@"a" forKey:strThread];
NSLog(@"a--%@",strThread);
[lock unlock];
}];
//注释1
// [op1 addExecutionBlock:^{
// [lock lock];
// NSThread *current = [NSThread currentThread];
// NSString *strThread = [NSString stringWithFormat: @"%@",current];
// [dicMuThreads setObject:@"a" forKey:strThread];
// NSLog(@"a--%@",strThread);
// [lock unlock];
// }];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
[lock lock];
NSThread *current = [NSThread currentThread];
NSString *strThread = [NSString stringWithFormat: @"%@",current];
[dicMuThreads setObject:@"b" forKey:strThread];
NSLog(@"b--%@",strThread);
[lock unlock];
}];
[op2 addExecutionBlock:^{
[lock lock];
NSThread *current = [NSThread currentThread];
NSString *strThread = [NSString stringWithFormat: @"%@",current];
[dicMuThreads setObject:@"b" forKey:strThread];
NSLog(@"b--%@",strThread);
[lock unlock];
}];
//注释2
// [op2 addExecutionBlock:^{
// [lock lock];
// NSThread *current = [NSThread currentThread];
// NSString *strThread = [NSString stringWithFormat: @"%@",current];
// [dicMuThreads setObject:@"b" forKey:strThread];
// NSLog(@"b--%@",strThread);
// [lock unlock];
// }];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
[lock lock];
NSThread *current = [NSThread currentThread];
NSString *strThread = [NSString stringWithFormat: @"%@",current];
[dicMuThreads setObject:@"c" forKey:strThread];
NSLog(@"c--%@",strThread);
[lock unlock];
}];
[op3 addExecutionBlock:^{
[lock lock];
NSThread *current = [NSThread currentThread];
NSString *strThread = [NSString stringWithFormat: @"%@",current];
[dicMuThreads setObject:@"c" forKey:strThread];
NSLog(@"c--%@",strThread);
[lock unlock];
}];
//注释3
// [op3 addExecutionBlock:^{
// [lock lock];
// NSThread *current = [NSThread currentThread];
// NSString *strThread = [NSString stringWithFormat: @"%@",current];
// [dicMuThreads setObject:@"c" forKey:strThread];
// NSLog(@"c--%@",strThread);
// [lock unlock];
// }];
NSOperationQueue *opeQueue = [[NSOperationQueue alloc]init];
[opeQueue setMaxConcurrentOperationCount:2];
[opeQueue addOperation:op1];
[opeQueue addOperation:op2];
[opeQueue addOperation:op3];
[opeQueue setSuspended: NO];
[opeQueue waitUntilAllOperationsAreFinished];
NSLog(@"线程总数是:%ld",dicMuThreads.count);
有注释1 注释2 注释3, 三处注释时结果如下
只取消注释2 时 结果如下:
只取消注释 1和 2时, 结果如下:
总结实验结果,规律比较清晰:setMaxConcurrentOperationCount 和当前 operation 的子任务数 (NSBlockOperation) 结合起来影响线程数 : maxConcurrentOperationCount 属性值为 2 时,则要开辟的线程数是,所有子任务中 NSBlockOperation 个数最多的 2 个子任务的 NSBlockOperation 个数之和;这样设计的原因也变的很合理。