在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
本文章翻译自appcoda,作者:Gabriel Theodoropoulos 多核多线程技术是中央处理单元(CPU)自出现以来最大的技术改进之一,此技术的存在意味着CPU可以在任何时刻同时执行多个任务。 串行任务执行或伪多任务执行已经存在多年,如果你经历过使用老式电脑的时代,或者如果你曾经有机会用旧操作系统的老式电脑,那么很容易理解我在说什么。但是无论CPU的内核数量多少,功能的强大程度如何,如果开发人员不利用这些可能性,这将变得毫无用处,因为才能让多任务和多线程编程发挥作用。开发人员可以且应该在任何设备上充分利用CPU的多任务功能,将程序可拆分的各个部分拆分到多个线程上并发执行。
多核多线程开发的优点有很多,最重要的有:能尽快地执行优先度高的任务、给用户最好的体验、避免界面卡顿等等。试想看,假如某些应用程序在主线程上下载一大堆图像,下载完成前UI将完全无发响应任何操作。可想而知,用户将不会再想去使用这样的应用程序。 在iOS中,苹果提供了两种方式去实现多任务处理:Grand Central Dispatch(GCD)和NSOperationQueue框架,这两者都能完美地分发任务于不同线程或者不同队列中。要使用哪一者取决于开发人员的决定,而这篇教程中我们将会把重点放在GCD的使用上。记住,多任务执行的使用有一条铁则:主线程应该永远用于界面展示和用户交互,任何耗时的或者高占用CPU的任务应该被放在并发队列或者后台队列中。这铁则对于新入门的开发人员来说或许难以消化且运用起来,但也必须要遵守它。
Grand
Central Dispatch最初是在iOS 4中引入的,它在尝试实现并发性、高性能和并行任务时提供了很大的灵活性和可定制性。在Swift 3之前,它有一个很大的缺点:晦涩的方法名让人难以记住和使用,因为它的编码风格与C相似,完全与Swift或者Objective-C的编码风格不同。这也是很多开发者故意避开GCD的主要原因,从而选择使用NSOperationQueue。网络上随意搜索有关于旧版本Swift中使用GCD的文章,都能让你更新UI感受到过去使用GCD的语法有多糟糕。
然而在Swift
3中这一情况不再存在。GCD的使用方式是全新的,完全类似于Swift,新的语法使得开发人员更容易熟悉它。这些改变让我有动力写一篇关于Swift 3中GCD的最基本和最重要用法的文章。如果你使用的是旧的编码风格(甚至是一点点)的GCD,那么这个全新的语法将让你无法抗拒;如果不是,那么你也很快能驾轻就熟。 在我们进入正文之前,我们先来谈一些关于GCD的概念。首先,GCD中的核心是dispatch queue。一个队列(queue)实际上是一个可以在主线程或后台线程上同步或异步执行的代码块。队列一旦被创建,操作系统便会接手对它的管理,并给它在CPU的任意内核上运行的时间。多队列也会有相应的管理,而这是开发人员不必处理的。队列之间是遵循FIFO(先进先出)模式的,这意味着首先被执行的队列代码也将首先完成(想象它像是在柜台前面排队的人,排前头的优先享受服务,排最尾的最后享受服务),我们后面会在例子中说明这一点。 另一个重要的概念是work item。一个work item其实就是将在dispatch queue中运行的代码块,可以在创建队列的同时写入队列,也可单独创建后让队列调用且它可被多次使用(重用)。队列中work item的执行顺序也遵循FIFO模式。Work item的执行可以是同步的或异步的。在同步的情况下,正在运行的应用程序在完成work item的代码前不会退出该代码块。而异步情况下,正在运行的应用程序会在调用work item后立即返回。同样,我们将在后面例子中看到这些差异。
上面所提到了(dispatch
queue和work item),在此说明队列的串行(serial)和并发(concurrent)之分。在串行情况下,一个work item将在上一个work item执行完后开始执行(除非它是在队列中分配的第一个work item),而在并发情况下,不同work item将并行(*译者注:这里不应该是并行,而应该是并发具体可见并发与并行的区别)同时执行。 当我们想要将任务分配到应用程序的主队列(main queue)时,必须保持谨慎。因为主线程应该始终保持可服务于用户的交互和用户界面的展示。说到这里,还有另一个铁则就是,当你想要作UI上的任何更新时必须始终在主线程上完成。如果你尝试在后台线程上进行UI更新,则无法保证是否会更新以及何时进行更新,并且很可能发生会让用户感受到不愉快的意外情况。但是,更新UI前所作的准备任务必须都已经完成,而这些任务完全允许后台进行。例如,你在次要的后台队列中下载图像的数据,但是你应该回到主线程上更新这些图像。 需要记住的是,队列并不总是需要自己创建的。系统会创建全局调度队列(global dispatch queues),可被用于任何想要你想要运行的任务。关于队列所在的线程,iOS维护Apple称之为线程池(a pool of threads)中的线程,意思是除主线程以外的线程集合,并且系统会选择一个或多个线程来使用(取决于创建队列的多少以及创建它们的方式)。使用哪个线程是开发人员无法控制的,而是由操作系统根据其他并发任务的数量,处理器的负载等情况来“决定”,我相信也不会有谁想要去自己控制。 测试环境 在这篇文章中,我们将使用小巧且具体的例子来阐述GCD的概念。通常情况下,我们不会去制作应用程序demo,而只用Xcode Playground进行工作,但是Playground中并不支持GCD的多线程使用。所以,我们将通过建立一个工程项目来克服所有有可能出现的困难,你可以在这里下载到它。 这几乎是一个空的工程,只做了以下两个添加:
下面将正式进入正文。 Dispatch Queues入门 在Swift 3中,创建一个新的dispatch queue最简单方法如下:
创建队列时你只需要给它赋予一个唯一的标签。使用逆序的DNS符号(“com.appcoda.myqueue”)是非常好的选择,因为它十分独特,这也是苹果推荐的做法。但这不是强制性的,只要保证标签唯一,使用任何字符串都是允许的。然而,队列的初始化方式不仅仅只有这一种;其实你可以在初始化时赋予更多的参数,我们会在后面谈论它。
一旦队列被创建,我们就可以用它来执行代码,可以使用一个叫做
红点是为了轻易区分控制台中的打印结果,特别是当我们添加更多的队列或执行更多任务的时候。
上面的
将上面的代码段复制粘贴到上面提供的Starter
Project下
这个
那假如我们使用 然后,运行并留意Xcode的控制台:
尽管上面的例子非常简单,但它清楚地体现了程序在同步队列和异步队列的运行行为不同。我们将在后面继续使用彩色的打印方式,要记住某个颜色是指在某个队列的任务执行结果,所以不同的颜色意味着不同的队列。 Quality Of Service (QoS) 和 Priorities
在使用GCD和dispatch
queue时,常常需要告诉系统:你的应用程序中哪些任务相对于其他任务更需要优先执行。当然,在主线程上运行的任务总是具有最高的优先级,因为主队列负责处理UI并时刻保持程序能响应操作。无论如何,通过向系统提供这些信息,iOS会保证列队以优先级顺序排列并提供所需的资源(如CPU的执行时间)。很自然,所有的任务最终都会得到完成,而区别在于哪些任务会更快完成,哪些更晚。
任务的重要程度和优先级相关的信息称为GCD 服务质量(Quality
of Service,简写为QoS)。事实上,QoS是一组具备特定类型的
现在回到我们的项目中,我们将在
可以注意到,我们给它们分配了相同的QoS类型,所以它们在执行期间具有相同的优先级。就像我们之前所做的那样,第一个队列将包含一个
我们现在看看,执行明知两个具有相同的优先级(相同QoS类型)队列的结果——不要忘了取消
通过查看上面的截图可以很容易地看出,这两个任务都是“均匀”执行的,实际上这是我们期望得到的结果。现在,让我们改变 让我们看看会发生什么:
毫无疑问,第一个调度队列( 我们来做另一个实验,这次我们将第一个队列的QoS类型改为background(后台): 这个优先级几乎是最低的,我们来看看在运行代码时会发生什么: 这次第二个队列的完成执行更快,因为QoS类型中background比utility具有更高的优先级。 以上内容让我们明确了QoS如何工作,但假如我们在主队列上执行任务会如何?让我们在方法的末尾添加下面的代码: 结果如下:
我们可以再次看到主队列默认具有高优先级,并且 Concurrent Queues(并发队列)到目前为止,我们已经看到dispatch queue是如何同步和异步地工作,以及Quality of Service各类型如何影响系统赋予队列的优先级。前面所有例子的共同点是,我们这些队列是串行(serial)的。这意味着,如果我们将多个任务分配给其中某个队列,那么这些任务将一个接一个地按顺序执行,而不是同时一起执行。接下来,我们将看到如何让多个任务(工作项)同时运行,换句话说,我们将看到如何创建一个并发队列。
进入我们的项目,来到
现在,让我们将以下任务(或者称为工作项)分配给队列: 当这段代码运行时,任务将以串行模式执行。这可在截图中很清楚看到:
接下来,让我们修改
上述初始化有一个新的参数:
通过再次运行程序,我们注意到这些任务几乎是并行执行的: 全部评论
专题导读
上一篇:[Swift]LeetCode650. 只有两个键的键盘 | 2 Keys Keyboard发布时间:2022-07-13下一篇:swift 集合类型(一)发布时间:2022-07-13热门推荐
热门话题
阅读排行榜
|
请发表评论