你的位置:首页 > 操作系统

[操作系统]IOS开发之多线程


前言:这篇GCD的博文是本人阅读了很多海内外大神的关于GCD的文章,以及结合之前自己对GCD的粗浅的认识,然后取其精华,去其槽粕,综合起来的笔记,而且是尽可能的以通熟易懂的并且是正确的理论论述方式呈现给大家,已经是尽可能的让大家掌握多线程的知识以及GCD的使用技术。最后的附录中,我将会给出所有本人阅读的大神写的关于多线程或者是GCD的文章链接,大家感兴趣的,可以去参考和学习。

本篇博文:持续更新,还未更新完。

 

相关基本概念

1、什么是GCD?

iOS实现提供实现多线程的方案有:NSThread、NSOperation、NSInvocationOperation、pthread、GCD。

在iOS所有实现多线程的方案中,GCD应该是最有魅力的,而且使用起来也是最方便的,因为GCD是苹果公司为多核的并行运算提出的解决方案。

GCD是Grand Central Dispatch的简称,它是基于C语言的。使用GCD,我们不需要编写线程代码,其生命周期也不需要我们手动管理,定义想要执行的任务,然后添加到适当的调度队列,也就是dispatch queue。GCD会负责创建线程和调度任务,系统直接提供线程管理。

 

2、任务(Task)

一段代码块,执行之后能够实现的一段业务逻辑过程。一般用闭包或者叫block,来包含它。执行任务,就需要将这个闭包或者block交给队列,然后让队列 先进先出(FIFO) 的顺序取出来,放进线程中执行。

 

3、队列(Queue)

我们需要了解队列的概念,GCD提供了dispatch queues来处理代码块,这些队列管理所提供给GCD的任务并用FIFO顺序执行这些任务。这样才能保证第一个被添加到队列里的任务会是队列中第一个开始的任务,而第二个被添加的任务将第二个开始,如此直到队列的终点。

  • 串行(Serial)队列

    串行队列 中的任务会根据队列定义 先进先出(FIFO) 的顺序取出来一个,执行一个,执行完了然后取出下一个任务,这样一个一个的执行。

    串行队列图:

   

  • 并发(Concurrent)队列

    并发队列 中的任务也会根据队列定义 先进先出(FIFO)的顺序一个个取出来,但是与串行队列不同的是,并发队列取出一个任务会放到别的线程中开始执行,先不管这个线程是同步线程还是异步线程,并发队列并不是等线程中的任务执行完了而是取完了这个任务,就会立刻接着从并发队列中取下一个任务放到别的线程中开始执行。由于取任务的速度很快,忽略不计,看起来,好像所有任务都是同时开始执行任务的。但是,任务又长又短,任务执行结束的顺序你是无法确定的,有可能那个最短的任务先执行完毕了。

    并发队列图:

   

补充:并发代码的不同部分可以“同步”执行。然而,该怎样发生或是否发生都取决于系统。多核设备通过并行来同时执行多个线程;然而,为了使单核设备也能实现这一点,它们必须先运行一个线程,执行一个上下文切换,然后运行另一个线程或进程。这通常发生地足够快以致给我们并发执行地错觉,如下图所示:

  

 

4、队列的类型(Queue Types)

系统提供的:

  • 一个主队列(main queue),是串行队列。

    和其它串行队列一样,这个队列中的任务一次只能执行一个。然而,它能保证所有的任务都在主线程执行,而主线程是唯一可用于更新 UI 的线程。这个队列就是用于发生消息给 UIView 或发送通知的。

   

  • 四个全局调度队列(Global Dispatch Queues),都是并行队列

    四个全局队列有着不同的优先级:background、low、default 以及 high。要知道,Apple 的 API 也会使用这些队列,所以你添加的任何任务都不会是这些队列中唯一的任务。

  • 你也可以创建自己的串行队列或并发队列。

   

总结:这就是说,至少有五个队列任你处置:主队列、四个全局调度队列,再加上任何你自己创建的队列。

以上是调度队列的大框架!

 

5、线程

  线程分为两种:Synchronous vs. Asynchronous 同步 vs. 异步。

  GCD创建同步线程和异步线程的方式:

  

  这里会有两个东西要说:同步函数和异步函数。我们的C语言基础就学了函数,函数用大括号包含了一段代码块,当这个函数执行完毕就会返回,可以是返回void或者返回具体某个数据值,同时也代表着这个函数的执行完毕。那么线程中的函数,当然是包含了任务的,这个任务就是闭包或者叫block。同步函数和异步函数的区别就在,同步函数需要在完成了它预定的任务后才返回,而异步函数会立即返回,也就是说异步函数预定的任务会完成但不会等它完成就立即返回。

  另外,同步线程是不具备创建子线程的能力的,一般情况下,同步线程的任务会在唯一的主线程中执行,也就是说唯一的(main)主线程就成了同步线程。而异步线程是具备创建子线程的能力的,一般情况下,异步线程就是(main)主线程以外的线程,不唯一,会有多个,具体多少个,具体是哪些线程,如果是通过GCD创建,全部由GCD决定。关于能创建的子线程的最大个数,这个就需要根据设备的CPU的能力了,比如下面是本人用真机,通过使用GCD创建了多个异步任务,并添加进并发队列执行测试的结果:

  

  可以发现,我创建了8个异步任务,GCD根据设备的极限,创建了三个子线程,分别是线程2、3、4,然后由它们随机执行任务。其中线程4执行了四个任务,线程2和线程3分别执行了两个任务。

  那么,同步还是异步,这两个术语是需要多个函数任务之间对比来论述的,这样会更好理解。比如说同步,当线程执行一个同步函数任务的时候,这个线程会停下来,也就是所谓的"当前这个线程阻塞"了,当前线程需要等待这个函数执行完毕返回了值,也表示这个函数中的任务完全执行完毕了,这个线程才会继续执行下去,去执行下一个函数任务,所以这样的线程也叫同步线程。而异步函数所在的线程就不一样了,线程开始执行一个异步函数任务的时候,因为异步函数立即返回了,虽然这个函数任务可能还没执行完毕,但是返回了,这个线程就会继续执行下一个函数任务,由于这个过程很快,快到可以忽略不计任务执行开始的先后顺序,快到感觉好像都是同时开始执行任务的,所谓的"异步线程同时执行多个任务"就是这么来的。

 

注意:

  不要将耗时操作放在主线程中,凡是跟UI相关的操作都是放在主线中处理

  耗时操作应该放在子线程(后台线程,非主线程)

 

 

 

附录:很好的GCD学习的网页链接

1、GCD这块已经开源,地址http://libdispatch.macosforge.org

2、唐巧的技术博客:《使用GCD》,地址:http://blog.devtang.com/2012/02/22/use-gcd/

3、大神翻译自国外IOS很不错的学习网站文章《Grand Central Dispatch In-Depth: Part 1/2》:https://github.com/nixzhu/dev-blog

4、标哥的技术博客:《GCD由浅入深学习》:http://www.henishuo.com/gcd-multiple-thread-learn/

5、土土哥的《GCD使用经验与技巧浅谈》:http://tutuge.me/2015/04/03/something-about-gcd/

6、YouXianMing老师的《Grand Central Dispatch (GCD) Reference》:http://www.cnblogs.com/YouXianMing/p/3600763.html

7、《关于IOS多线程,你看我就够了》:http://www.jianshu.com/p/0b0d9b1f1f19