【问题标题】:NSOperationQueue many threadsNSOperationQueue 多线程
【发布时间】:2026-02-09 03:55:02
【问题描述】:

在我们的 iPhone 应用程序中,我们有几个选项卡,选择每个选项卡都会触发网络连接。过去我们只是为每个连接分离新线程。在几个非常快速的选项卡切换应用程序变得无响应之后。 现在我们决定使用应该控制线程数并且不应该让应用程序变得无响应的操作队列。但是现在,即使使用较少的快速开关,应用程序也会变得无响应(尽管现在它可以更快地从无响应中恢复)。 我从 xcode 在设备上运行该应用程序,并在几次快速切换后暂停它以查看线程数。我发现有几个线程具有以下堆栈:

    0 __workq_kernreturn
    2 _init_cpu_capabilities

知道这些线程是什么以及如何摆脱它们吗?

【问题讨论】:

    标签: iphone multithreading nsurlconnection nsoperation nsoperationqueue


    【解决方案1】:

    使用 NSOperationQueue 的一大好处是您可以忘记线程,让系统为您担心。听起来您的问题的根源在于您有几个不再需要的操作同时运行。与其担心特定的线程,不如考虑让这些操作终止,这样它们就不会再耗尽计算资源。

    对于它的价值,我猜这些线程是由 Grand Central Dispatch 管理的。 GCD 将创建工作线程来处理块(和操作),它会尽可能高效。

    【讨论】:

    • 这就是我们决定切换到 NSOperationQueue 的原因(忘记线程,让系统来担心)。实际上,我的操作并不占用太多 CPU,它们只是创建一个 NSURLConnection(同步)并在主线程上执行回调。
    【解决方案2】:

    问题的重要部分可能并不在于工作线程的内部/私有实现。一个好的实现可能会使用线程池,因为每个操作创建一个线程会花费很多。操作可以重用并保持空闲线程。

    重要的部分(可能)在于您对所选实现的公共 API 的使用。

    在这种情况下支持的一个明显实现是操作取消:-[NSOperation cancel]。当有人离开一个有待处理/未完成请求的视图时,只需取消它(除非您需要缓存数据)。

    许多实现也可以通过减少请求次数而受益。例如:如果您的服务器结果大约每小时更新一次,那么“大约每分钟”请求它是没有意义的。

    最后一点:连接本身可以使用工作线程 - 如果出现问题,请检查您正在使用的 api 以减少这种情况。

    【讨论】:

    • 实际上,我并没有取消先前的请求,而是跟踪正在进行的请求,并且在同一请求正在进行时不添加操作。我猜我提到的线程是池线程(如您所述),也许限制 maxConcurrentOperationCount 是合理的。
    • 正确 - 如果它们不能取消并且可以稍后使用,那么可以设置上限 - 坏消息是,如果您不取消,您正在等待的重要操作将不会很快完成。在类似情况下下载一堆图像时,我发现大约 4 个 url 连接可以最快地在屏幕上显示内容(但该模型也支持取消)。
    • 我认为取消已经运行的操作不是一种选择,因为该操作的主要作用是发出同步 HTTP 请求。当 HTTP 请求正在进行时,取消不会停止它。在收到回复后,取消它是不合理的。所以,我唯一检查取消的地方是在发出 HTTP 请求之前。
    • 正确。您已经提出的要点:1)如果您的请求是异步的,则 NSURLConnection 支持取消 2)在请求开始之前取消请求也是合理的。如果您限制了最大操作数,那么您很可能能够在请求开始之前取消此场景。其中大部分归结为下载您正在下载的任何内容所需的时间。 (续)
    • (cont) 如果您的下载大小不是微不足道的,两者都是选项 - 但您必须衡量/比较并确定在您的特定情况下什么是最好的。 afaik,您仍然可以选择缓存结果。