Grand Central Dispatch vs. NSThread [英] Grand Central Dispatch vs. NSThread

查看:83
本文介绍了Grand Central Dispatch vs. NSThread的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为NSThread和Grand Central Dispatch(GCD)创建了一些测试代码:

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);
 });
}

结果:

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秒。

NSThreads work as I expected: The tasks run concurrently and each thread sleeps for 1 second.

dispatch_apply不能按预期工作:为什么订单顺序?为什么每个循环都等到上一个循环结束?

The dispatch_apply does not work as I expected: Why is the order sequential? Why does each loop wait until the previous loop finishes?

感谢您的帮助。

推荐答案

因为您的设备只有一个处理器,GCD可能只创建一个用于执行块的线程,并且您的块按顺序执行。但是,您创建了10个不同的线程,每个线程都可以获得一小部分可用的处理时间。幸运的是,睡眠并不是处理器密集型的,因此所有线程都可以很好地协同运行。在具有4或8个处理核心的机器上尝试类似的测试,你会看到GCD并行运行更多的块。

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.

关于GCD的好处不是'它必然提供比线程更好的性能,它是程序员不必考虑创建线程或将线程数与可用处理器数量相匹配。您可以创建许多小任务,这些任务将在处理器可用时执行,并让系统为您安排这些任务。

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.

编辑:我在我的Mac上的一个简单的命令行程序中使用你的代码。正如我在下面的评论中提到的那样,并且在@ Ren-D的回答中也提到过,使用 dispatch_async()而不是 dispatch_apply()有很大的不同。这是我使用的代码:

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 than dispatch_apply() makes a big difference. Here's the code I used:

- (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);
}

如你所见,我更换了你的睡眠( )使用调用循环,花费一些时间计算。 (我在MacBook Pro上运行代码 - 如果你在iPhone上运行,你可能想要向下调整 MAX_COUNT 的值。)如果你使用<$ c线程和块中的$ c> sleep(),然后 dispatch_async()使块的行为就像线程一样 - 所有块大约在同一时间同时运行并完成。切换到计数会改变这种行为 - 多个线程都同时运行,但这些块在组中执行(我的机器有两个处理器核心,所以它以两个为一组运行块)。这正如你所期望的那样; GCD的工作是尽可能快地排队任务并完成它们,充分利用可用资源,而不是尽可能多地同时运行任务。

As you can see, I replaced your sleep() calls with for loops that spend some time counting. (I ran the code on a MacBook Pro -- you might want to adjust the value of MAX_COUNT downward if you're running on an iPhone.) If you use sleep() in both the threads and the block, then dispatch_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.

这是来自上面的代码:

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

注意两个除了其中一个线程之外,块实际上已完成。另外:代码末尾的 sleep(15)就是让线程和块在程序终止之前记录它们的消息。根据您将代码粘贴到哪种程序,您可能不需要它。

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.

这篇关于Grand Central Dispatch vs. NSThread的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆