深入理解Grand Central Dispatch (GCD)(一)

来源:互联网 发布:什么叫一级域名 编辑:程序博客网 时间:2024/05/06 04:01

多线程

首先,线程是什么?如果你有一些计算机的基础知识,这可能难不倒你。
应用程序启动后,首先便将包含在应用程序中的CPU命令列配置到内存中。CPU从应用程序指定的地址开始,一个一个地执行CPU命令列。
虽然Objectve-C中的if语句和for语句等控制流语句或者函数调用的情况下,执行命令列的地址会远离当前的位置。但是,由于一个CPU一次只能执行一个命令,不能同时执行两个命令,因此CPU执行的命令就像是一条无分叉的道路。
“一个CPU执行的命令为一条无分叉的路径”即为“线程”。
通过CPU分时,或者多核CPU可以实现多线程。
多线程看上去是好事,实际上,多线程编程极易发生各种问题,比如:

  • 数据竞争
  • 死锁
  • 太多线程导致消耗大量内存

下文中会有对这三点的描述

Dispatch Queue

苹果官方对GCD有一段描述:

开发者要做的只是定义想执行的任务并追加到适当的Dispatch Queue中。

对这句话的理解应当聚焦在两个关键词上——“任务”和“Dispatch Queue”
Dispatch Queue即队列,它是任务的队列,上面按顺序排列着任务。所以,任务又是什么?任务可以看做是代码片段,一段代码,一个函数。我们用下面的方式把任务追加到Dispatch Queue上时,任务是Block。

dispatch_async(queue,^{/**想执行的任务*/});

串行队列和并发队列

Dispatch Queue有两种,分别是:Serial Dispatch Queue和Concurrent Dispatch Queue,即串行队列和并发队列。
串行队列中的每个任务是串行执行的,按照任务追加的顺序,等待一个任务执行完成后再执行下一个任务。
并发队列里的每个任务是并发执行的,不等待现在执行的任务结束就可以执行下一个任务。
假设向队列queue中依次追加8个任务blk0~blk7

dispatch_async(queue,blk0);dispatch_async(queue,blk1);dispatch_async(queue,blk2);dispatch_async(queue,blk3);dispatch_async(queue,blk4);dispatch_async(queue,blk5);dispatch_async(queue,blk6);dispatch_async(queue,blk7);

当变量queue为串行队列时,因为要等待现在执行中的任务结束,所以先执行blk0,等blk0执行完成后执行blk1,然后是blk,2,blk3,如此重复。即执行该源代码后,一定按照下面的顺序执行处理。
blk0->blk1->blk2->blk3->blk4->blk5->blk6->blk7
当queue为并发队列时,因为不用等待现在执行中的任务处理结束,所以先执行blk0,不管blk0的执行是否完成,都开始执行后面的blk1,不管blk1执行是否完成,都开始执行后面的blk2,如此重复循环。

Dispatch Queue(队列)与线程

虽然并发队列不用等待任务处理结束,可以并行执行对个任务,但是并行执行的任务数量取决于当前系统的状态。即基于Dispatch Queue中的处理数、CPU核数以及CPU负荷等当前系统的状态来决定并发队列中并行执行的任务数量。所谓”并行执行“就是使用多个线程同时执行多个处理。
上面的源码,假设系统准备了四个线程

线程0 线程1 线程2 线程3 blk0 blk1 blk2 blk3 blk4 blk6 blk5 blk7

任务的执行状况,可由上表表示

而一个串行队列只使用一个线程。

dispatch_queue_create

我们知道了有两种Dispatch Queue,那么怎么获得Dispatch Queue呢?有两种方法,第一种就是自己创建一个Dispatch Queue。
如果你想创建一个串行队列:

dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("mySerialQueue",NULL);

如果你想创建一个并发队列:

dispatch_queue_t myConcurrentDispatchQueue = dispatch_queue_create("myConcurrentlQueue",DISPATCH_QUEUE_CONCURRENT);

dispatch_queue_create函数的第一个参数是队列的名称,接受一个C语言字符串。第二个参数是队列的类型,如果串行队列就为NULL,并发队列指定为DISPATCH_QUEUE_CONCURRENT。
就像前面所说的,每一个串行队列使用一个线程,在使用dispatch_queue_create创建多个串行队列是,相当于创建了多个线程。由于创建过多的线程会消耗大量的内存,所以不要一激动就创建大量串行队列。创建串行队列必须有充足的理由。

Main Dispatch Queue/Global Dispatch Queue

第二种获取队列的方法就是获取系统标准提供的Dispatch Queue。
系统提供两个Dispatch Queue。Main Dispatch Queue和Global Dispatch Queue。
Main Dispatch Queue就是在主线程中执行的队列。是串行队列。
Global Dispatch Queue是一个并发队列。
Global Dispatch Queue有四个优先级,分别是高优先级,默认优先级,低优先级和后台优先级。四种优先级只是大致的优先程度区分。
获得各种系统提供Dispatch Queue的方法:

/**Main Dispatch Queue的获取方法*/dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();/**Global Dispatch Queue的获取方法*/dispatch queue_t globalDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)

可以改变dispatch_get_global_queue的第一个参数,获得不同优先级的Global Dispatch Queue。

0 0
原创粉丝点击