适用于初学者的iOS多线程策略

并发是编程中最复杂的(读作“ 吓人” )主题之一。 这是一个非常强大的工具,可以为您的应用程序带来魔力。 但是,如果使用不当,还会带来讨厌的问题。 作为iOS的初级程序员,如果不知道如何挥动这把双刃剑,就无法改善。 今天,我将帮助您在iOS中使用多线程。

什么是线程?

Apple的文档将线程定义为“一种在应用程序内部实现多个执行路径的相对轻量级的方法。”为了简化起见,您可以想象每个线程都是一个cookie怪物,每个cookie怪物都有自己的cookie队列(代码等待执行)。

多线程很棒。

iOS要求在主线程中执行与UI相关的代码。 将UI代码想象成M&M cookie; 因此,所有M&M Cookie只能进入主要Cookie怪物。 如果我们只有一个Cookie怪兽,其中包含许多种Cookie(用于UI的M&M,用于网络连接的巧克力芯片等),那么M&M Cookie的执行速度将非常慢,因为其他Cookie太多了。 我们会看到该应用程序的响应速度不太快,甚至会冻结,因为主要怪物无法足够快地进入M&M Cookie。

采用并发就像让多个饼干怪兽吃饼干一样。 如果您可以指定一个怪物只吃巧克力(网络处理)饼干,一个怪物只吃花生酱(数据存储和缓存)饼干,并且仅将M&M(UI)饼干喂给主要的饼干怪物,那么所有饼干将以更快,更清洁的方式被食用。 这就是多个线程如何提高应用程序性能的方式。 您可以通过两种常见的方式在应用程序中放置更多的Cookie怪物:Grand Central Dispatch和NSOperationQueue。

第一种方式:大中央调度(GCD)

由于这是针对初学者的指南,因此我将开始介绍如何以最简单的方式使用GCD。

让我们将一个cookie怪物的cookie行命名为“调度队列”。 您可以通过以下方法获取公共调度队列:

  • dispatch_get_main_queue :这是主线程的队列。
  • dispatch_get_global_queue :系统为每个应用程序提供四个并发调度队列,您可以使用此方法获取任何共享的并发队列。 它们非常适合于后台任务。
  • dispatch_get_current_queue :这将返回当前队列

您还可以通过dispatch_queue-create(queue_name, NULL).自己的串行调度队列dispatch_queue-create(queue_name, NULL).

现在您站在传送带(队列)上,开始将每个cookie(代码)包装到袋子(块)中。 您可以通过两种方式分发cookie:(1)将打包的cookie放在队列中,然后继续制作其他cookie和执行其他任务。 在这种情况下,您不必担心Cookie何时到达Cookie怪物,或该Cookie之前或之后有多少Cookie; (2)这是一个重要的cookie,您可以停止等待cookie到达cookie怪物。 在这种情况下,您尝试执行其他任何操作之前先确保已吃掉Cookie。

对于第一种情况,您是异步地将代码块分派到队列中。 在代码中看起来像这样:

第二种方式:NSOperationQueue

GCD是同时分发Cookie的一种很好的简单方法。 但是,当您的cookie工厂变得越来越复杂时,您将需要对cookie和cookie行进行更多控制。 现在该探讨NSOperation和NSOperationQueue。

NSOperation是一个智能盒,您可以将其放入Cookie中。 其中一些可以包含多个cookie,一些可以处理自定义大小的cookie。 您可以指示小甜饼怪兽如何在每个包装盒中食用小甜饼,并以不同的优先级标记它们。 框中有一些按钮,可让您将Cookie标记为“已过期”(取消操作),还具有标签来显示Cookie是被食用还是已完成。

NSOperationQueue是用于处理智能盒子的升级传送带。 您可以根据需要添加任意数量的皮带,并且可以在一个皮带中同时放置多个智能Cookie盒。 这些升级的传送带带有“手柄”,因此您可以暂停或恢复NSOperationQueue。 您也可以取消皮带上的所有包装盒,或等待队列将所有包装盒交付给Cookie怪物。 相当强大的并发工具,不是吗?

当饼干怪物变成真正的怪物

如果您不谨慎地将cookie分配给cookie怪物,那么将会发生不好的事情。 例如,两个曲奇怪物可能会尝试同时吃同一张曲奇并引起战斗。 更具体地说,当两个线程尝试同时将一个属性更改为不同的值时,或者当一个线程在另一个线程尝试读取该属性的同时更改属性时,可能会出现不想要的结果,甚至使应用程序崩溃。 这种错误是最难调试的错误,因为在跟踪所有线程的同时很难重现确切的问题。

两个cookie怪兽之间的争斗可能非常血腥,而两个线程之间的资源争夺会导致您意外的灾难。 接下来,我将介绍一种快速简便的方法来将您从Cookie怪物大战中解救出来。

快速解决方案:同步

通过同步,您可以锁定对cookie的访问,并且一次只允许一个cookie怪物打开它。 您可以按照Apple的指导方针找到创建锁的多种方法,但是最简单的方法是使用@synchronized指令。 它仅需要任何类型的Objective-C对象作为令牌,如下所示:

尽管同步很容易实现,但是此解决方案有两个缺点:

  • 它很容易失去多线程的并发优势。 该锁强制应用程序使用相同的锁序列化代码的过程。 如果到处同步,则将使代码再次变慢。
  • 它可以引入死锁。 想象一下,方法addM&MToCookie收到令牌以运行代码,但是它需要等待bakeCookieDough首先完成。 但是bakeCookieDough具有相同的锁,正在等待addM&MToCookie完成并释放令牌…将不会执行任何代码,也不会为cookie怪物提供cookie!

结论

这是有关Objective-C和iOS中多线程的快速教程。 当然,还有很多东西要学习。 我建议您从Apple文档“并行编程指南”开始:https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/ TP40008091-CH1-SW1。