Como su dispositivo solo tiene un procesador, GCD probablemente solo cree un hilo para ejecutar bloques y sus bloques se ejecuten secuencialmente. Sin embargo, ha creado 10 subprocesos diferentes, y cada uno obtiene una pequeña parte del tiempo de procesamiento disponible. Afortunadamente, dormir no requiere mucho del procesador, por lo que todos tus hilos se ejecutan bastante bien. Pruebe con una prueba similar en una máquina con 4 u 8 núcleos de procesamiento, y verá que GCD ejecuta más bloques en paralelo.
Lo bueno de GCD no es que ofrezca necesariamente un mejor rendimiento que los hilos, sino que el programador no tiene que pensar en crear hilos o hacer coincidir el número de hilos con la cantidad de procesadores disponibles. Puede crear muchas pequeñas tareas que se ejecutarán cuando un procesador esté disponible y permita que el sistema programe esas tareas por usted.
Edit: He jugado un poco con su código en un sencillo programa de línea de comandos en mi Mac. Como sugerí en mi comentario a continuación, y también mencionado en la respuesta de @ Ren-D, usar dispatch_async()
en lugar de dispatch_apply()
hace una gran diferencia. Aquí está el código utilicé:
- (void)doIt:(NSNumber *)i
{
for (int j = 0; j < MAX_COUNT; j++)
;
NSLog(@"Thread#%i", [i intValue]);
}
- (void)doWork:(id)sender
{
for (int i = 0; i<10; i++) {
NSNumber *t = [NSNumber numberWithInt:i];
[NSThread detachNewThreadSelector:@selector(doIt:) toTarget:self withObject:t];
}
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (size_t i = 0; i<10; i++) {
dispatch_async(queue, ^(void) {
for (int j = 0; j < MAX_COUNT; j++)
;
NSLog(@"GCD#%u",(int)i);
});
}
NSLog(@"Done.");
sleep(15);
}
Como se puede ver, he sustituido sus sleep()
llamadas con for
bucles que pasan algún tiempo contando. (Ejecuté el código en una MacBook Pro; es posible que desee ajustar el valor de MAX_COUNT
hacia abajo si está ejecutando en un iPhone). Si utiliza sleep()
en los hilos y en el bloque, entonces dispatch_async()
hace que los bloques se comporten solo al igual que los hilos: todos los bloques se ejecutan al mismo tiempo y se completan aproximadamente al mismo tiempo. Cambiar a contar cambia ese comportamiento: todos los subprocesos se ejecutan simultáneamente, pero los bloques se ejecutan en grupos (mi máquina tiene dos núcleos de procesador, por lo que ejecutó los bloques en grupos de dos). Esto es exactamente lo que esperas; El trabajo de GCD consiste en poner en cola tareas y terminarlas lo más rápido posible aprovechando al máximo los recursos disponibles, no ejecutar tantas tareas al mismo tiempo como sea posible.
Aquí es resultado del código anterior:
2011-04-14 02:48:46.840 BlockTest[14969:903] Hello, World!
2011-04-14 02:48:47.104 BlockTest[14969:903] Done.
2011-04-14 02:48:52.834 BlockTest[14969:1503] Thread#0
2011-04-14 02:48:52.941 BlockTest[14969:4f03] GCD#0
2011-04-14 02:48:52.952 BlockTest[14969:5003] GCD#1
2011-04-14 02:48:52.956 BlockTest[14969:4703] Thread#8
2011-04-14 02:48:53.030 BlockTest[14969:3703] Thread#4
2011-04-14 02:48:53.074 BlockTest[14969:2b03] Thread#1
2011-04-14 02:48:53.056 BlockTest[14969:4b03] Thread#9
2011-04-14 02:48:53.065 BlockTest[14969:3b03] Thread#5
2011-04-14 02:48:53.114 BlockTest[14969:3303] Thread#3
2011-04-14 02:48:53.138 BlockTest[14969:4303] Thread#7
2011-04-14 02:48:53.147 BlockTest[14969:3f03] Thread#6
2011-04-14 02:48:53.156 BlockTest[14969:2f03] Thread#2
2011-04-14 02:48:53.909 BlockTest[14969:4f03] GCD#2
2011-04-14 02:48:53.915 BlockTest[14969:5003] GCD#3
2011-04-14 02:48:54.700 BlockTest[14969:4f03] GCD#4
2011-04-14 02:48:54.721 BlockTest[14969:5003] GCD#5
2011-04-14 02:48:55.508 BlockTest[14969:4f03] GCD#6
2011-04-14 02:48:55.550 BlockTest[14969:5003] GCD#7
2011-04-14 02:48:56.321 BlockTest[14969:4f03] GCD#8
2011-04-14 02:48:56.345 BlockTest[14969:5003] GCD#9
Tenga en cuenta que dos de los bloques realmente terminado antes de todos menos uno de los hilos. Además: el sleep(15)
al final del código está ahí para permitir que los hilos y bloques registren sus mensajes antes de que el programa finalice. Dependiendo de en qué tipo de programa pegue el código, puede que no lo necesite.
Así que en un GCD dispositivo IOS es inútil? Y debería usar NSThreads? – CarlJ
No, en absoluto. Pruebe dispatch_async() en su lugar. – Caleb
la otra respuesta es correcta. dispatch_apply es sincrónico. – XJones