我很喜欢NSOperationQueue
,但我在理解其中某些部分时遇到了一些问题。
在the second issue of objc.io中,他们回顾了NSOperationQueue,并提到它有两种队列,即主线程上运行的主队列和后台队列。他们提到您可以使用[NSOperation mainQueue]
访问主队列,然后添加操作它。
它还提到你可以通过创建NSOperation的实例(潜在的子类)来添加到后台队列(我理解会更好吗?)。
mainQueue
这样的后台队列单例,那么如何管理向后台队列添加任务呢?它还提到您可以控制与maxConcurrentOperationCount
属性同时运行的操作量。
NSOperationQueueDefaultMaxConcurrentOperationCount
,但如果我手动将其设置为特定数字,它是否与一次可以运行的最大线程数相对应?例如,如果iPhone上的处理器可以同时运行4个线程并且我将该属性设置为8,会发生什么?答案 0 :(得分:17)
你问:
您通常不希望[向
mainQueue
添加操作],对吗?如果它在主线程上运行,它是否会阻止主线程执行其他任务?它不会与其他任务同时运行吗?
是的,你永远不想在主队列中添加任何慢的东西。但这并不意味着您不使用主队列。对于某些操作(例如UI更新),这很关键。
典型的模式是为要在后台运行的任务创建操作队列,但是如果您随后需要执行需要在主队列上运行的操作(例如UI更新,更新模型等)。 ),你会继续这样做,例如:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
// do some time consuming stuff in the background
// when done, you might update the UI in the main queue
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// update the UI here
}];
];
你问:
我是否保存对我为操作创建的
NSOperationQueue
的引用,以便创建更多操作?我假设没有像mainQueue那样的后台队列单例,那么如何管理向后台队列添加任务呢?
是的,如果您想稍后向同一队列添加更多操作,是的,您希望维护对该队列的引用。您可以通过将其添加到应用程序委托,某个中央视图控制器或单例来完成此操作。
但是,是的,背景队列没有内置的单例(因为可以想象,不同的队列可以有不同的操作,例如一个用于网络操作,一个用于图像处理等)。但是,如果需要,您可以为每种类型的每个队列编写自己的单例。
你也问:
我通常知道您将其设置为
NSOperationQueueDefaultMaxConcurrentOperationCount
,但如果我手动将其设置为特定数字,它是否与一次可以运行的最大线程数相对应?例如,如果iPhone上的处理器可以同时运行4个线程并且我将该属性设置为8,会发生什么?
应该将maxConcurrentOperationCount
设置为您认为适合队列类型的任何内容。对于网络操作队列,通常不会超过4,但对于其他类型的队列,您可能很容易拥有更多。我相信最多有64个工作线程(并发队列因为需要线程而自行使用)。
如果您尝试使用更多,则在工作线程可用之前,应用程序将不会启动您的操作。不过,Apple建议不要使用所有工作线程。因此,请使用适合您队列功能的合理数字。坦率地说,操作队列优于调度队列的一个优点是,您可以限制在任何给定时间将使用的最大工作线程数,以更好地管理设备的有限资源。
WWDC 2012视频Asynchronous Design Patterns with Blocks, GCD, and XPC是一些关于某些GCD模式的优秀入门读物,并涉及“太多线程”问题。
Building Concurrent User Interfaces on iOS视频介绍了构建并发iOS应用的一些实际意义。
线程编程指南的About Threaded Programming部分涉及核心和线程之间的关系。
并发编程指南的Concurrency and Application Design部分是对线程与操作/调度队列之间关系的清晰讨论。
答案 1 :(得分:0)
通常您不想使用主队列。那里的任何操作都将在主线程上运行。
创建操作队列时,请将其创建用于某个目的。就像它将用于所有服务器请求。因此,您可以控制正在进行的并发请求数。因此,不要将算法处理操作添加到此队列,因为它们具有不同的用途。保留对队列的引用,以便将来添加操作(以及暂停/取消操作)。
maxConcurrentOperationCount
没有“正常”设置 - 应根据目的设置。
如果将其设置为8,则队列将同时运行最多8个。这可能不是最有效的选择。始终牢记队列的目的。
答案 2 :(得分:0)
首先,您必须记住,您始终将主线程与后台线程分开。只有涉及更新UI的操作必须在主线程中执行,其余操作必须在后台线程中执行。例如,如果您正在处理多次下载,则必须在后台队列中处理所有基于网络的操作,并且您必须在主队列中执行UI更新。
//e.g for updating UI in main thread.
[self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:YES];
当您使用set maxConcurrentOperationCount属性作为NSOperationQueueDefaultMaxConcurrentOperationCount时,这意味着operationQueue将根据系统环境获取并发操作的数量。
有用的链接:
http://mobile.tutsplus.com/tutorials/iphone/nsoperationqueue/
http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues
http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/