GCD概述
什么是GCD?
GCD(Grand Center Dispatch)是异步执行任务的技术之一。开发者定义想执行的任务并且追加到适当的Dispatch Queue中,GCD就能生成必要的线程并计划执行任务。
多线程编程
一个CPU一次只能执行一个命令,不能执行某处分开的并列的两个命令,所以通过CPU执行的CPU命令列就好比一条无分叉的大道,其执行不会出现分歧。就像下图一样:
==这里所说的“一个CPU执行的CPU命令列为一条无分叉路径”就是线程。==同时存在多条这样的路径就称为“多线程”。
但是多线程编程时会出现很多问题,使用GCD大大简化了偏于复杂的多线程编程的源代码,并且可以避免多线程的一些缺点。
GCD的API
Dispatch Queue
上面我们说到GCD是:开发者定义想执行的任务并且追加到适当的Dispatch Queue中。这句话可以用下面这段源代码表示:
dispatch_async (queue, ^{
//想执行的任务
}
该源代码使用Block语法“定义想执行的任务”,通过dispatch_async
函数“追加”赋值在变量queue的“Dispatch Queue
”中。仅这样就可使指定的Block在另一线程中执行。
Dispatch Queue是什么呢?是执行处理的等待队列,按照追加任务的顺序(先进先出)执行处理。如下图:
在执行处理时,存在两种Dispatch Queue,一种是等待现在执行中处理的Serial Dispatch Queue
,另一种是不等待现在执行中处理的Concurrent Dispatch Queue
。二者执行情况如下图:
二者和线程的关系:
在执行Concurrent Dispatch Queue
中执行处理时,执行顺序会根据处理内容和系统状态发生改变。而Serial Dispatch Queue
则顺序固定。
既然知道了有两种Dispatch Queue
,那么如何去创建呢?有以下两种方法:dispatch_queue_create
和获取系统标准提供的Dispatch Queue
。
dispatch_queue_create
第一种方法是通过GCD的API生成Dispatch Queue
,通过dispatch_queue_create
函数可生成Dispatch Queue
:
dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.example.gcd.MySerialDispatchQueue", NULL);
参数列表:
第一个参数指定Serial Dispatch Queue
的名称,命名推荐使用应用程序ID这种逆序全程域名。
第二个参数:生成Serial Dispatch Queue
类时,则指定为NULL,生成Concurrent Dispatch Queue
时,指定为DISPATCH_QUEUE_CONCURRENT
。
说明:使用dispatch_queue_create
函数可以生成任意多个Dispatch Queue
,如果过多使用会消耗大量内存。但是使用多个Serial Dispatch Queue
可以避免多线程编程引起的多个线程对数据的竞争:
dispatch_queue_create
的返回值为dispatch_queue_t
类型。
生成的Dispatch Queue
必须由程序员手动释放。
dispatch_release(queue);
有release,则可推断出相应地存在dispatch_retain函数,通过这两个函数的引用计数来管理内存。
这里立即通过dispatch_release
释放是没有问题的,原因:在dispatch_async
中追加Block到Dispatch Queue
,也就是说,该Block通过dispatch_retain
函数持有Dispatch Queue
,即使立即释放Dispatch Queue
,该Dispatch Queue
由于被Block所持有也不会被释放,一旦Block执行结束后,这时谁都不再持有Dispatch Queue
,就通过dispatch_release函数释放该block持有的Dispatch Queue
。
Main Dispatch Queue/Global Dispatch Queue
第二种方法就是获取系统标准提供的Dispatch Queue
。那就是Main Dispatch Queue
和Global Dispatch Queue
。
Main Dispatch Queue
是在主线程中执行的Dispatch Queue
,因主线程只有一个,所以Main Dispatch Queue
就是Serial Dispatch Queue
。追加到Main Dispatch Queue
中的处理是在主线程的RunLoop
中执行的,因此要将用户界面的界面更新等一些必须在主线程中执行的处理追加到Main Dispatch Queue
使用。