IOS开发--网络篇-->GCD(Grand Central Dispatch)的详解

GCD(Grand Central Dispatch)

 

FIFO(先入先出)

Dispatch(派遣,急件,分派

Serial (连续的,连载的,分期偿还的

Dispatch Queue(调度队列)

Serial Dispatch Queue(串行调度队列

Concurrent Dispatch Queue(并发调度队列

Main Dispatch Queue(主要调度队列

Global Dispatch Queue(全局调度队列

dispatch_apply是(同步函数

 

GCD是从OS X Snow Leopard和iOS 4开始引入的新一代的多线程编程技术

libdispatch是苹果的一个库

开发者只需定义想执行的任务并追加到适当的Dispatch Queue中,GCD就能生成必要的线程并有计划的执行任务。并且由于线程管理是作为系统的一部分来实现的,因此系统可以统一管理,它会决定什么时候创建新线程,创建哪些新线程,多个任务是顺序执行还是并发执行。这样就比以前的线程编程更有效率

 

Dispatch Queue(调度队列)

使用GCD进行编程,开发者要做的只是定义想执行的任务并追加到适当的Dispatch Queue中。其中,“定义想执行的任务”使用Block语法来完成。Dispatch Queue中的任务按照FIFO(先入先出)的顺序进行处理,也就是先进入的任务先处理。另外,Dispatch Queue分为串行并发两种。

 

Serial Dispatch Queue(串行调度队列)要求等待正在执行的任务完成,再执行下一个

而Concurrent Dispatch Queue(并发调度队列)中后面的任务可以不必等待正在执行的任务执行完成就可以开始执行,也就是同时可以执行多个任务。

换句话说,其实就是Serial Dispatch Queue只会创建一个线程来执行任务,而Concurrent Dispatch Queue会创建多个线程同时执行多个任务

对于Concurrent Dispatch Queue,OS X和iOS的XNU内核会基于Dispatch Queue中的任务数量CPU核数CPU负荷等当前系统状态来决定创建多少个线程和并行执行多少个任务。

 

一般情况下:如果要求在不能改变执行顺序或不想并行执行多个任务时使用Serial Dispatch Queue

简言之:Serial Dispatch Queue串行代码;Concurrent Dispatch Queue并行代码

 

一、创建队列

dispatch_queue_create 用于创建用户线程队列。可以创建Serial/Concurrent Dispatch Queue 两种队列,即串行与并行队列。

1、创建串行队列

dispatch_queue_t serialQueue =

  dispatch_queue_create(“com.SerialQueue”, NULL);

可以创建多个串行队列,串行队列也可以并行执行

不能随意的大量生产Serial Dispatch Queue。每创建一个串行队列,系统就会对应创建一个线程,同时这些线程都是并行执行的,只是在串行队列中的任务是串行执行的。大量的创建串行队列会导致大量消耗内存,这是不可取的做法

 

2、创建并行队列

dispatch_queue_t concurrentQueue =

  dispatch_queue_create(“com.ConcurrentQueue”,

    DISPATCH_QUEUE_CONCURRENT);

并发队列创建多少都没有问题,因为Concurrent Dispatch Queue所使用的线程由系统的XNU内核高效管理,不会影响系统性能。

 

3、内存管理

由dispatch_queue_create方法生成的Dispatch Queue并不能由ARC来自动管理内存。可以使用dispatch_release、dispatch_retain来手动管理(引用计数式)。

 

二、Main&Global Dispatch Queue

系统为我们提供了两种调度队列 这两种队列不需要我们创建 只是在我们使用时获取一下

Main Dispatch Queue是在主线程中执行任务的Dispatch Queue。因为主线程只有一个,所以Main Dispatch Queue是Serial Dispatch Queue

追加到Main Dispatch Queue中的任务将在主线程中执行。因为是在主线程中执行,所以应该只将用户界面更新等一些必须在主线程中执行的任务追加到Main Dispatch Queue中。

获取Main Dispatch Queue的代码如下:

dispatch_queue_t dispatch_main_queue = dispatch_get_main_queue();

 

Global Dispatch Queue是全局都能使用的Concurrent Dispatch Queue

大多数情况下,可以不必通过dispatch_queue_create函数生成Concurrent Dispatch Queue,而是只需要获取Global Dispatch Queue使用即可。

Global Dispatch Queue有四个优先级,分别是high、default、low、background

获取Global Dispatch Queue的代码如下:

dispatch_queue_t dispatch_global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

 

三、dispatch_async 和dispatch_sync

dispatch_sync(),同步添加操作。他是等待添加进队列里面的操作完成之后再继续执行。

dispatch_async() ,异步添加进任务队列,它不会做任何等待

四、dispatch_group

如果想在dispatch_queue中所有的任务执行完成后再做某种操作,在串行队列中,可以把该操作放到最后一个任务执行完成后继续,但是在并行队列中怎么做呢。这就有dispatch_group成组操作

创建一个group

使用dispatch_group_async向组中添加队列和任务

当并行队列中的任务执行完时,使用dispatch_group_notify执行通知任务

 

五、dispatch_barrier_async

使用用户创建的并行队列

在并行队列中,使用dispatch_barrier_async添加的任务,队列在执行此任务时,队列中的其他任务不会执行,执行完成后该队列恢复原有执行状态,继续并行执行

六、dispatch_apply

dispatch_applydispatch_syncdispatch_group的关联API

dispatch_apply是同步函数,会阻塞当前线程直到所有循环中任务执行完成。这些任务在queue中的执行顺序是不确定的(要并发,要提高效率)

dispatch_apply函数是将指定次数的指定任务(block)添加到queue中

 

七、dispatch_semaphore

dispatch_semaphore 信号量基于计数器的一种多线程同步机制。在多个线程访问共有资源时候,会因为多线程的特性而引发数据出错的问题。

 

信号量是一个整型值并且具有初始数值,信号量通常支持两个操作:通知和等待。当信号被通知的时候计数值会增加,当信号量在线程上等待的时候,必要的情况下线程会被阻塞掉,直至信号被通知时计数值大于0,然后线程会减少这个计数继续工作

 

GCD中有3个信号量有关的操作:

dispatch_semaphore_create    信号量创建

dispatch_semaphore_wait     信号量等待  

dispatch_wait  会阻塞线程并且检测信号量的值,直到信号量值大于0才会开始往下执行,同时对信号量执行-1操作.

dispatch_semaphore_signal    发送通知 +1

 

下载图片

 

更新UI

 

创建一个信号量  1

等待   减一 ,执行代码

通知   信号量计数+1

 

八、dispatch_once 实现单例中的线程同步

使用dispatch_once函数

该函数参数1 dispatch_once用于检查代码块是否已经被调度的谓词(其实就是长整形,实际上作为BOOL使用)

参数2 希望在程序的生命周期内仅被调用一次的代码块(适用于单例)

如果被多个线程同时调用,该函数会同步等待 直至代码块完成

优势

1 ,线程安全

2 ,和自动引用计数(ARC)兼容 

3 ,仅需要少量代码

4 ,很好满足静态分析器要求

 

并发VS并行

1,并发说的是多任务 并行说的是多线程

2,并行要求并发

3,并发并不能保证并行(单核)

 

多任务同时执行并不代表者开辟多线程

task1:_ _ __ ___

task2: _ _  _

 

并行

task1:——————

task2:——————

 

原文地址:https://www.cnblogs.com/gegeboke/p/4324583.html