2014-02-18 32 views
0

我需要处理大量来自NSDictionary的数据到NSManagedObjects(3k-10k对象)。Objective C和线程

在同步处理中,3K花费约60秒:

for (NSString *key in myDictionary) { 
    //process data 
} 

当我使用GCD和用于每个键创建一个新的线程,大约需要20秒,使用一串线程:

for (NSString *key in myDictionary) { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     //process data 
    } 
}  

然后我试图使用NSOperationQueueNSBLockOperation和用于每个键,添加块执行历时约30秒和只用2个线程:

NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
NSBlockOperation *operation = [[NSBlockOperation alloc] init]; 

for (NSString *key in myDictionary) { 
    [operation addExecutionBlock:^{ 
    // processs data 
    } 
} 

[operation setCompletionBlock:^{ 
    DLog(@"Block completed | time: %f", [[NSDate date] timeIntervalSinceDate:startTime]); 
}]; 

[queue addOperation:operation]; 

这给出了具有完成块的优点。

就速度而言,每个按键的线程似乎是最快的。

所有时间在设备上完成,而不是模拟器。

我读过NSOperation vs GCD,他们建议使用更高层次的API,即NSOperation,但GCD的性能更好。

使用NSOperationQueueNSBlockOperation除完成块外还有什么优势吗?或者我错过了一些让队列和块本来就比GCD更好的东西?

+0

相关:http://stackoverflow.com/questions/18632271/what-is-the-差异之间的nsinvocationoperation和nsblockoperation –

+3

在Objective-C中有大约六种不同的线程方式。除非有特别的理由选择其中一种,否则使用你理解最好并且最舒服的技术。线程混淆不清,在复杂情况下使用不熟悉的界面只会增加混淆。 –

回答

2

或者我错过了让队列和块本身更好的GCD?

你不会错过任何东西 - 操作是使用GCD实现的。正如你所看到的,拥有更高层次的API比直接的GCD更好,但最终操作本质上与使用GCD不同。

+0

我很好奇为什么操作只使用2线程,而GCD使用30+(线程ID在30年代,而不是100%肯定有30+线程)? – Padin215

+1

我不认为使用多于一个线程。有一个线程池,所以你得到的踏板是“随机的”。 GCD在该池的不同线程上分派块,但AFAIK永远不会在不同线程上执行一个块。 (你的调度不在for循环中。)每个线程都有自己的栈,因此从一个线程移动到另一个线程将非常昂贵。 –

+0

那么你会如何解释GCD快10秒?我记录[NSThread currentThread]和GCD,我看到很多线程ID,而操作只使用2个线程ID? – Padin215

1

正如前面提到的操作和操作队列是建立在GCD之上的。但有一些区别:

  • 操作队列可以有一个宽度。 GCD只知道串行或并发队列。
  • 操作队列可以处理依赖关系。
  • 操作可以有一个优先级(加)
  • GCD可以处理“运行循环的东西”(系统事件)

正如我在评论中提及您的GCD代码只使用一个线程:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    for (NSString *key in myDictionary) { 
     //process data 
    } 
} 

试试这个并将结果报告,请:

for (NSString *key in myDictionary) { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     //process data 
    } 
} 
+0

Bah!你是对的,我用手输入了我的代码,但我做错了。我正在使用第二种方法。修正了错误。感谢您注意到这一点。 – Padin215

+0

所以你很清楚你有不同的线程。 ;-) –

+0

是的,这就是我打字得太快了。 = d – Padin215