I'm using iPhone SDK 3.1.2, and the following code shows the NSOperationQueue does not reuse the thread for each task.
The code does not have any problems on Snow Leopard.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
[window addSubview:viewController.view];
[window makeKeyAndVisible];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue setMaxConcurrentOperationCount:1];
for(int i = 0; i < 100; i++) {
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
[queue addOperation:op];
[op release];
}
}
- (void)run {
static int tc = 0;
if([[NSThread currentThread] isMainThread]) {
NSLog(@"MAIN THREAD");
return;
} else if([[NSThread currentThread] name] == nil) {
[[NSThread currentThread] setName:[NSString stringWithFormat:@"THREAD_%d", tc++]];
}
NSLog(@"%@", [[NSThread currentThread] name]);
}
The output shows it create 100 threads to execute the 100 tasks.
2010-01-07 11:46:03.502 OperationQueueTest[7911:4503] THREAD_0
2010-01-07 11:46:03.506 OperationQueueTest[7911:4d03] THREAD_1
2010-01-07 11:46:03.507 OperationQueueTest[7911:4807] THREAD_2
2010-01-07 11:46:03.510 OperationQueueTest[7911:4d07] THREAD_3
2010-01-07 11:46:03.514 OperationQueueTest[7911:5007] THREAD_4
2010-01-07 11:46:03.516 OperationQueueTest[7911:4f0b] THREAD_5
2010-01-07 11:46:03.518 OperationQueueTest[7911:4e0f] THREAD_6
...
2010-01-07 11:46:03.740 OperationQueueTest[7911:4ea7] THREAD_97
2010-01-07 11:46:03.744 OperationQueueTest[7911:4dcf] THREAD_98
2010-01-07 11:46:03.746 OperationQueueTest[7911:460f] THREAD_99
NSOperationQueue is designed to pool and re-use threads in the most efficient way possible and in this instance, it seems it decided not re-using threads was the best way to go.
Test code has it's uses (and it is possible you may have identified a corner case where NSOperationQueue does not do the most efficient thing), but that doesn't mean that NSOperationQueue is always horribly inefficient when dealing with real code in real life; in fact my own experience has been to the contrary.
So I'd say use it in your real code and if you have performance issues, dig further into what it's doing with threads behind the scenes. Otherwise don't worry about it.
As an aside, if you are still curious, you might try recording the names of the threads into an array of NSStrings and then printing everything out at the end of the test code, rather than logging as you go along - this will significantly reduce the amount of work done by each NSInvocationOperation.
Snow Leopard's implementation of NSOperation/NSOperationQueue is now based on GCD.
The iPhone still uses the old Leopard implementation. So you can expect different results on each platform (Not to mention the completely different hardware).
It is possible that spawning new threads is the most efficient way to accomplish the tasks you are giving NSOperationQueue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With