前言:最近对公司项目代码优化, 优化过程中经常遇到GCD的处理问题,开发结束了,有点空余时间就对这部分知识总结一下, 方便以后查看!
一.什么是GCD
GCD全称为Grand Central Dispatch,是libdispatch的市场名称,而libdispatch是Apple的一个库,其为并发代码在iOS和OS X的多核硬件上执行提供支持。确切地说GCD是一套低层级的C API,通过 GCD,开发者只需要向队列中添加一段代码块(block或C函数指针),而不需要直接和线程打交道。GCD在后端管理着一个线程池,它不仅决定着你的代码块将在哪个线程被执行,还根据可用的系统资源对这些线程进行管理。这样通过GCD来管理线程,从而解决线程被创建的问题。
二.GCD的优点
- 灵活: GCD 具有在常见模式上(比如锁、单例),用更高性能的方法优化代码,而且GCD能提供更多的控制权力以及大量的底层函数。
- 易用: GCD 提供一个易于使用的并发模型而不仅仅只是锁和线程,以帮助我们避开并发陷阱,而且因为基于block,它能极为简单得在不同代码作用域之间传递上下文。
- 性能: GCD能自动根据系统负载来增减线程数量,这就减少了上下文切换以及增加了计算效率。
二.GCD的优点
二.GCD相关储备知识点
学习GCD,必须要储备以下知识点.
- Dispatch Objects :
尽管GCD是纯C语言的,但它被组建成面向对象的风格。GCD对象被称为dispatch object, 所有的dispatch objects都是OC对象.,就如其他OC对象一样,当开启了ARC(automatic reference counting)时,dispatch objects的retain和release都会自动执行。而如果是MRC的话,dispatch objects会使用dispatch_retain和dispatch_release这两个方法来控制引用计数。
- Serial & Concurrent:
串行任务就是每次只有一个任务被执行,并发任务就是在同一时间可以有多个任务被执行。
- Synchronous & Asynchronous:
同步函数意思是在完成了它预定的任务后才返回,在任务执行时会阻塞当前线程。而异步函数则是任务会完成但不会等它完成,所以异步函数不会阻塞当前线程,会继续去执行下一个函数。
- Concurrency & Parallelism:
并发的意思就是同时运行多个任务。这些任务可能是以在单核 CPU 上以分时(时间共享)的形式同时运行,也可能是在多核 CPU 上以真正的并行方式来运行。然后为了使单核设备也能实现这一点,并发任务必须先运行一个线程,执行一个上下文切换,然后运行另一个线程或进程。并行则是真正意思上的多任务同时运行。
- ** Context Switch:**
Context Switch即上下文切换,一个上下文切换指当你在单个进程里切换执行不同的线程时存储与恢复执行状态的过程。这个过程在编写多任务应用时很普遍,但会带来一些额外的开销。
- Dispatch Queues:
GCD dispatch queues是一个强大的执行多任务的工具。Dispatch queue是一个对象,它可以接受任务,并将任务以先进先出(FIFO)的顺序来执行。Dispatch queue可以并发的或串行的执行任意一个代码块,而且并发任务会像NSOperationQueue那样基于系统负载来合适地并发进行,串行队列同一时间则只执行单一任务。Dispatch queues内部使用的是线程,GCD 管理这些线程,并且使用Dispatch queues的时候,我们都不需要自己创建线程。Dispatch queues相对于和线程直接通信的代码优势是:Dispatch queues使用起来特别方便,执行任务更加有效率。
-
Queue Types:
GCD有三种队列类型
Serial:串行队列将任务以先进先出(FIFO)的顺序来执行,所以串行队列经常用来做访问某些特定资源的同步处理。你可以也根据需要创建多个队列,而这些队列相对其他队列都是并发执行的。换句话说,如果你创建了4个串行队列,每一个队列在同一时间都只执行一个任务,对这四个任务来说,他们是相互独立且并发执行的。如果需要创建串行队列,一般用dispatch_queue_create这个方法来实现。
Concurrent:并发队列虽然是能同时执行多个任务,但这些任务仍然是按照先到先执行(FIFO)的顺序来执行的。并发队列会基于系统负载来合适地选择并发执行这些任务。在iOS5之前,并发队列一般指的就是全局队列(Global queue),进程中存在四个全局队列:高、中(默认)、低、后台四个优先级队列,可以调用dispatch_get_global_queue函数传入优先级来访问队列。而在iOS5之后,我们也可以用dispatch_queue_create,并指定队列类型DISPATCH_QUEUE_CONCURRENT,来自己创建一个并发队列。
**Main dispatch queue: **与主线程功能相同。实际上,提交至main queue的任务会在主线程中执行。main queue可以调用dispatch_get_main_queue()来获得。因为main queue是与主线程相关的,所以这是一个串行队列。和其它串行队列一样,这个队列中的任务一次只能执行一个。它能保证所有的任务都在主线程执行,而主线程是唯一可用于更新 UI 的线程。
二.GCD的使用与实例
==创建队列和管理队列==
当你决定添加一些任务到队列中时,你需要决定该用那种类型的队列,并且抉择该如何使用他们。Dispatch queues可以串行或并发地执行这些任务,当你脑海里有一个大概的思路去如何使用队列时,你可以额快速地设置好队列的属性。接下来的部分,本文将告诉大家如何创建队列和怎样设置队列的属性。
- 获取一个全局队列
当我们需要同时执行多个任务时,并发队列是非常有用的。并发队列其实仍然还是一个队列,它保留了队列中的任务按先进先出(FIFO)的顺序执行的特点。同时,一个并发队列可以移除t它多余的任务,甚至这些任务之前还有未完成的任务。一个并发队列中实际执行的任务数是由很多因素决定的,比如系统的内核数,其他串行队列中任务的优先级,以及其他进程的工作状态。
系统为每个程序提供了四种全局队列,这些队列中仅仅通过优先级加以区别,这四种类型分别是高、中(默认)、低、后台。因为这些队列是全局的,所以大家不能直接创建它们,取而代之的是我们可以通过dispatch_get_global_queue这个方法来调用它们。
// 获取全局队列
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 全局队里的类型
DISPATCH_QUEUE_PRIORITY_HIGH
DISPATCH_QUEUE_PRIORITY_DEFAULT
DISPATCH_QUEUE_PRIORITY_LOW
DISPATCH_QUEUE_PRIORITY_BACKGROUND
详细请参考:https://ecgbao.github.io/2017/04/14/Grand-Central-Dispatch/