I created some test code for NSThread and Grand Central Dispatch (GCD):
- (void)doIt:(NSNumber *)i
{
sleep(1);
NSLog(@"Thread#%i", [i intValue]);
}
- (IBAction)doWork:(id)sender
{
for (int i = 0; 10 > i; i++) {
NSNumber *t = [NSNumber numberWithInt:i];
[NSThread detachNewThreadSelector:@selector(doIt:) toTarget:self withObject:t];
}
sleep(1);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10, queue, ^(size_t i) {
sleep(1);
NSLog(@"GCD#%u",(int)i);
});
}
And the results:
2011-04-13 19:41:07.806 GDC[1494:5e03] Thread#0
2011-04-13 19:41:07.813 GDC[1494:6903] Thread#3
2011-04-13 19:41:07.812 GDC[1494:6403] Thread#2
2011-04-13 19:41:07.812 GDC[1494:5f03] Thread#1
2011-04-13 19:41:07.813 GDC[1494:6e03] Thread#4
2011-04-13 19:41:07.814 GDC[1494:7303] Thread#5
2011-04-13 19:41:07.814 GDC[1494:7803] Thread#6
2011-04-13 19:41:07.815 GDC[1494:7d03] Thread#7
2011-04-13 19:41:07.815 GDC[1494:8203] Thread#8
2011-04-13 19:41:07.816 GDC[1494:8703] Thread#9
2011-04-13 19:41:08.812 GDC[1494:707] GCD#0
2011-04-13 19:41:09.816 GDC[1494:707] GCD#1
2011-04-13 19:41:10.819 GDC[1494:707] GCD#2
2011-04-13 19:41:11.825 GDC[1494:707] GCD#3
2011-04-13 19:41:12.828 GDC[1494:707] GCD#4
2011-04-13 19:41:13.833 GDC[1494:707] GCD#5
2011-04-13 19:41:14.838 GDC[1494:707] GCD#6
2011-04-13 19:41:15.848 GDC[1494:707] GCD#7
2011-04-13 19:41:16.853 GDC[1494:707] GCD#8
2011-04-13 19:41:17.857 GDC[1494:707] GCD#9
NSThreads work as I expected: The tasks run concurrently and each thread sleeps for 1 second.
The dispatch_apply does not work as I expected: Why is the order sequential? Why does each loop wait until the previous loop finishes?
Thanks for the help.
If anyone want to test, which method is the best for the spedify probleme, here ist the code:
Because your device only has one processor, GCD probably only creates one thread for executing blocks and your blocks execute sequentially. You've created 10 different threads, though, and those each get a little piece of the available processing time. Fortunately, sleeping isn't very processor-intensive, so all your threads run together pretty well. Try a similar test on a machine with 4 or 8 processing cores, and you'll see GCD run more of your blocks in parallel.
The nice thing about GCD isn't that it necessarily offers better performance than threads, it's that the programmer doesn't have to think about creating threads or matching the number of threads to the number of available processors. You can create lots of little tasks that will execute as a processor becomes available and let the system schedule those tasks for you.
Edit: I played around with your code a bit in a simple command-line program on my Mac. As I suggested in my comment below, and also mentioned in @Ren-D's answer, using
dispatch_async()
rather thandispatch_apply()
makes a big difference. Here's the code I used:As you can see, I replaced your
sleep()
calls withfor
loops that spend some time counting. (I ran the code on a MacBook Pro -- you might want to adjust the value ofMAX_COUNT
downward if you're running on an iPhone.) If you usesleep()
in both the threads and the block, thendispatch_async()
makes the blocks behave just like the threads -- all blocks run concurrently and complete at about the same time. Switching to counting changes that behavior -- multiple threads all run concurrently, but the blocks execute in groups (my machine has two processor cores, so it ran the blocks in groups of two). This is exactly as you'd expect; GCD's job is to queue tasks and finish them as quickly as possible making the best use of available resources, not to run as many tasks concurrently as possible.Here's output from the code above:
Note that two of the blocks actually finished before all but one of the threads. Also: the
sleep(15)
at the end of the code is just there to let the threads and blocks log their messages before the program terminates. Depending on what sort of program you paste the code into, you may not need it.Try to look at this website: http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html
In IOS environment, It is said that
dispatch_apply
will depend on the queue passed in, if the target queue is a concurrent queue returned bydispatch_get_global_queue
(which is your case), the block can be invoked concurrently.So, I think it IS working, just so it happens that it is run as if it runs asynchronously. Also, which device the code is run at could play a role on the result (like mentioned by @Caleb). But my suggestion is, maybe try
dispatch_async
instead?