Grand Central Dispatch与NSThread

| 我为NSThread和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);
 });
}
结果:
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按我的预期工作:任务同时运行,每个线程睡眠1秒。 dispatch_apply无法按我预期的方式工作:为什么订单是顺序的?为什么每个循环都等到前一个循环结束? 谢谢您的帮助。     
已邀请:
由于您的设备只有一个处理器,因此GCD可能仅创建一个线程来执行块,并且您的块按顺序执行。但是,您已经创建了10个不同的线程,并且每个线程都只占可用处理时间的一小部分。幸运的是,睡眠不是很消耗处理器,因此所有线程都可以很好地运行。在具有4个或8个处理核心的机器上尝试类似的测试,您会看到GCD并行运行更多的块。 GCD的好处在于,它不一定提供比线程更好的性能,而是程序员不必考虑创建线程或将线程数与可用处理器数进行匹配。您可以创建许多小任务,这些任务将在处理器可用时执行,并让系统为您安排这些任务。 编辑:我在Mac上的一个简单命令行程序中使用了您的代码。正如我在下面的评论中所建议的那样,并且也在@ Ren-D \的答案中提到,使用
dispatch_async()
而不是
dispatch_apply()
会有很大的不同。这是我使用的代码:
- (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);
}
如您所见,我将
sleep()
呼叫替换为
for
循环,这花费了一些时间。 (我在MacBook Pro上运行了代码-如果在iPhone上运行,您可能想向下调整
MAX_COUNT
的值。)如果在线程和块中都使用
sleep()
,则
dispatch_async()
会使块起作用就像线程一样-所有块同时运行并大约同时完成。切换到计数更改行为-多个线程全部同时运行,但这些块按组执行(我的机器有两个处理器内核,因此它以两个为一组运行这些块)。这正是您所期望的; GCD的工作是将任务排入队列并尽快完成它们,以充分利用可用资源,而不是同时运行尽可能多的任务。 这是上面代码的输出:
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
请注意,除了一个线程外,其中两个块实际上已在所有线程之前完成。另外:代码末尾的“ 11”仅用于使线程和块在程序终止之前记录其消息。根据您将代码粘贴到哪种程序中,您可能不需要它。     
尝试查看此网站:http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html 在IOS环境中,据说ѭ12将取决于传入的队列,如果目标队列是ѭ13返回的并发队列(这是您的情况),则可以同时调用该块。 因此,我认为它正在运行,恰好碰巧它像异步运行一样运行。同样,运行代码的设备可能对结果有影响(如@Caleb所提到的)。但是我的建议是,也许尝试
dispatch_async
?     
如果有人要测试,哪种方法最适合解决问题,请在此处输入代码:
#define MAX_COUNT 99999999
#define HOW_MUCH 10
- (void)doIt:(NSNumber *)i
{
    for (int j = 0; j < MAX_COUNT; j++)
        ;
    NSLog(@\"Thread#%i\", [i intValue]);
}


- (IBAction)doWork:(id)sender
{
    NSLog(@\"START\");

    for (int i = 0; i < HOW_MUCH; i++) {
        NSNumber *t = [NSNumber numberWithInt:i];
        [NSThread detachNewThreadSelector:@selector(doIt:) toTarget:self withObject:t];
    }

    sleep(3);


    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_apply(HOW_MUCH, queue, ^(size_t i) {
        for (int j = 0; j < MAX_COUNT; j++)
            ;
        NSLog(@\"GCD APPLY %u\",(int)i);
    });


    sleep(3);

    for (size_t k = 0; k < HOW_MUCH; k++) {
        dispatch_async(queue, ^(void) {
            for (int j = 0; j < MAX_COUNT; j++)
                ;
            NSLog(@\"GCD ASYNC#%u\",(int)k);
        });
    }

    sleep(10);
    NSLog(@\"DONE\");
}
    

要回复问题请先登录注册