今天,我以昨天学习的成果对GCD进行简单的图文概括一下。
1.GCD是什么?核心概念是什么?
下文来源于百科
GCD为Grand Central Dispatch的缩写。
Grand Central Dispatch (GCD)是Apple开发的一个多核编程的较新的解决方法。它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并行任务。在Mac OS X 10.6雪豹中首次推出,也可在IOS 4及以上版本使用...
从上文可以得知,GCD实际上是:多线程处理系统。
而多线程处理的核心概念就是任务和队列。
2.队列、任务的概要及创建方法
2.1 概要
1.任务
简要说,就是线程中处理的一段代码。在GCD中,任务是放在block中处理的代码段落。
任务本身又具备俩种执行类型,第一种:同步执行(sync),第二种:异步执行(async)。
首先我们来说说俩种执行方法的概念以及区别:
同步执行(sync)
1.当新任务以同步执行方式添加到队列中执行任务时,会等待前方所有任务执行完再执行自身的任务。
2.同步执行中的任务,不会单独开启新线程处理,只会在当前线程执行任务。
异步执行(sync)
1.当新任务以异步执行方式添加到队列中执行任务时,并不会等待前方所有任务执行结果直接执行。
2.异步执行方式会单独开启一条新线程,可以在新线程中执行任务。
3.虽然具备开启新线程的能力,但是不一定都会开启。开启与否与队列类型有关。
2. 队列(Dispatch_queue)
队列这里指的是:用来执行任务的等待队列。即用来存放任务的队列。
队列是一种特殊的线性表,采用的是FIOI(先进先出)的原则,即新任务被插入队列,而读取任务时总是从头部开始读取任务。每读取一个任务,则从队列释放一个任务。
队列分作俩种类型分别为,串行队列(serial_dispatch_queue)、并发队列(concurrent_dispatch_queue)
串行队列:
串行队列中,每次只能执行一个任务,任务是一个接着一个执行的。任务执行完毕才会执行下一个,并不会另起多线程处理。
并发队列:
并发队列中,一次可以执行多个任务,任务可以同一时间在不同线程中执行。
2.2 创建方式
2.2.1队列创建
dispatch_queue_t queue = dispatch_queue_create("参数1","参数2");
参数1:队列的唯一标识符,可用于debug等调试。可为nil
参数2:队列的类型
1.串行队列:dispatch_queue_serial
2.并发队列:dispatch_queue_concurrent
* 除了上述提到的队列创建方式,苹果官方还给予了特殊的队列创建方式
主队列
dispatch_queue_t queue = dispatch_get_main_queue();
备注:
1.主线程队列默认为串行队列类型。
2.所有放在主队列的任务,都会在主线程中来处理
3.一般使用dispatch_get_main_queue获取。
全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORATY_DEFAULT,0);
备注:全局并发队列默认为并发队列,一般使用dispatch_get_global_queue获取。需要传入俩个参数值。第一个为队列的优先级,一般用DIS_PATCH_QUEUE_PRIORATY_DEFAULT表示优先级,第二个表示的是保留字段备用,但是一般都填0。
2.2.2 任务的创建
dispatch_sync(queue,^{ //同步任务 });
dispatch_async(queue,^{ //异步任务 });
任务和队列的创建只有俩部,但是俩种队列(并发、串行) + 俩种执行方式(同步、异步)以及主线程的排列组合下
会诞生以下六种组合方式
对应关系,以EXCEL表达如下
现在我们假想有俩个任务,任务一及任务二。
任务一本质为一个for循环,每2秒执行一次,打印输出"1"。
任务二同上,但是打印输出为"2"。
任务二在任务一后面,执行结束后队列为空关闭。
并在开始以及结束分别打印"start","end"。
以此为基础以下列组合会出现什么样的结果?
* 斜杠 "/" 代表等待 "2秒" 。逗号"," 代表在同一秒中内出现。数字代表输出结果。
实测得出:
并发队列 + 同步执行 = start - > /1/1/2/2 - >end 费时8秒
结论1:所有任务都按顺序执行打印
结论2:虽然并发队列拥有开启多个线程,同时处理多个任务的能力。但是如果当前执行方式不具备开启新线程能力时,任务还是按当前顺序进行执行。
结论3:任务在start和end中执行。
并发队列 + 异步执行 = start - > end - > /1,2 / 2,1 费时4秒
结论4:任务在start和end之后打印,说明线程没有做任何等待。直接另外开启新线程执行当前待处理任务。
串行队列 + 同步执行 = start - > /1/1/2/2 - > end 费时8秒
同结论1,3。
串行队列 + 异步执行 = start - > end - > /1/1/2/2 费时8秒
结论5:.异步执行虽然具有开启新线程能力,但是如果当前队列不具备并发执行能力时,任务还是得按照当前顺序执行。
主线程:主队列 + 同步执行 = start - > 报错
报错原因:当在主线程中调用主队列(get_main_queue)时,并用同步执行方式将当前线路任务1、任务2加入主队列中时。
因为同步执行会在当前队列执行完任务后再执行新加入任务,因此任务1、任务2执行会在主线程任务执行结束后执行主队列任务。而主线程中的主队列本身也需要等待任务1、任务2执行完毕后才会接着执行任务。因此引发了loop报错。
其他线程:主队列 + 同步执行 = start - >1/1/2/2 -> end 费时8秒
结论6:当在其他线路中调用主队列(get_main_queue)时,因为获取主线程的方法在其他线程中将任务加入到主线程,而此时主队列任务为空,所以可以正确的将任务1、任务2加入主线程当中。按照任务一、任务二的顺序执行。不会执行循环报错
当前线程:主队列 + 异步执行 = start - > end - > 1/1/2/2 耗时8秒
结论7:虽然异步执行具有开启新线程的能力,但是因为主队列拥有“主队列中的任务都在主队列中执行”这一特性,所以所有任务都在主队列中。(此处解释有些牵强、建议结合代码自身测试理解)。
以上便是昨天自身对GCD中关于任务和队列的学习
后续文章会补上GCD中具体使用方式。