GCD总结

前言

为了缓解主线程的压力除了优化算法,性能等一列措施之外,我们用的最多的应该就是多线程,通过开辟一个分线程,让一些耗时的操作在分线程完成来释放主线程压力,这种方式简单也很高效。但线程并不是越多越好,开辟线程同样需要消耗性能( 开辟新线程:主线程(1M),子线程(512k)),但是实在开发应用中,建议开启线程条数:3~5条最为合理。

GCD实现原理:

GCD有一个底层线程池,这个池中存放的是一个个的线程。之所以称为“池”,很容易理解出这个“池”中的线程是可以重用的,当一段时间后这个线程没有被调用胡话,这个线程就会被销毁。注意:开多少条线程是由底层线程池决定的(线程建议控制再3~5条),池是系统自动来维护,不需要我们程序员来维护,而我们程序员需要关心的是什么呢?我们只关心的是向队列中添加任务,队列调度即可。

1.队列只是负责任务的调度,而不负责任务的执行

2.任务是在线程中执行的

先来说一个队列和任务:

队列分为串行队列与并行队列

任务的执行分为同步任务与异步任务

这两两组合就成为了串行队列同步执行,串行队列异步执行,并行队列同步执行,并行队列异步执行

而异步是多线程的代名词,异步在实际引用中经常会开启新的线程,执行耗时操作,这里为什么说是经常,因为并不是所有的异步任务都会开启一个线程,这个问题后面会具体说道。

队列和任务的特点:

队列的特点 :先进先出,排在前面的任务最先执行,

串行队列:任务按照顺序被调度,前一个任务不执行完毕,队列不会调度

并行队列:只要有空闲的线程,队列就会调度当前任务,交给线程去执行,不需要考虑前面是都有任务在执行,只要有线程可以利用,队列就会调度任务。

主队列:专门用来在主线程调度任务的队列,所以主队列的任务都要在主线程来执行,主队列会随着程序的启动一起创建,我们只需get即可。现将任务放在主队列中,但是不是马上执行,等到主队列中的其它所有除我们使用代码添加到主队列的任务都执行完毕之后才会执行我们使用代码添加的任务。

全局队列:是系统为了方便程序员开发提供的,其工作表现与并发队列一致,那么全局队列跟并发队列的区别是什么呢?

1.全局队列:无论ARC还是MRC都不需要考录释放,因为系统提供的我们只需要get就可以了

2.并发队列:再MRC下,并发队列创建出来后,需要手动释放dispatch_release()

同步执行:不会开启新的线程,任务按顺序执行,当一个任务没有执行完成,不会开始执行新的任务。

异步执行:会开启新的线程,任务可以并发的执行,当一个任务开始执行,下个任务不需要等待前置任务完成即可开始执行。

今天研究的目录

1.串行队列里添加同步任务

2.串行队列添加异步任务

3..并行队列里添加同步任务

4.并行队列添加异步任务

5.全局并发对列

6.主队列

7.并行队列里异步任务嵌套同步任务

8.并行队列里异步任务嵌套异步任务

9.串行队列里异步任务嵌套同步任务

10.串行队列里异步任务嵌套异步任务

11.串行队列里同步任务嵌套同步任务

12.延迟执行

13.定时器

14.group之同步任务

15.group之异步任务

16.apply

17.barrier(栅栏)

18.信号量

接下来一个一个看

1.串行队列里添加同步任务


首先串行队列所有任务依次执行,向串行队列里添加同步任务,同步任务特点,不会开启线程并且当前任务执行完才会执行下一个任务,所以输出顺序为1,2,3。

2.串行队列添加异步任务


从结果可以看到执行顺序还是依次执行,虽然添加的是异步任务,造成这种现象是因为串行队列的特点,就算你是异步任务但还是得按我的规矩来,和上面相比不同的是开辟了一个分线程去执行,因为异步任务具备开启分线程的能力,那么问题来了,为什么三个异步任务只开启一个分线程?这是因为串行队列所有任务顺序执行,开启三个也还是顺序执行,倒不如只开启一个,毕竟开启分线程也是消耗性能的。

3.并行队列里添加同步任务


同步任务的特点,不会开启新的线程并且当前任务执行完才能执行下个任务,那么就算你是并发队列也没什么卵用了,只能依次执行。

4.并行队列添加异步任务


真正能实现并发操作的只有这情况,执行顺序是1,3,2,开启了三个线程来执行任务

5.全局并发对列


系统提供的并发队列,直接获取就行。

6.主队列


主队列不管异步还是同步,都不会开启新的线程,只能在主线程执行。

7.并行队列里异步任务嵌套同步任务


queue是一个并行队列,首先调用dispatch_async函数,将block添加到队列里,由于是异步任务所以会开启一个分线程并且不用等到block的代码执行完就可以继续往下走,所以结束和1谁先执行并不确定,在结束前将主线程休眠2秒,这样1会先走,执行完1接着又调用dispatch_sync函数,将block添加到队列里,由于这是一个同步任务,所以block会立刻执行,接着输出2,当主线程休眠结束会输出结束,结束和2谁先执行也是不确定的,如果主线程休眠时间长,那么2先输出,反之结束先输出,之所以不确定,是因为2在分线程里,所以什么时候会执行无法确定。


8.并行队列里异步任务嵌套异步任务


这个和上面那个并行队列里异步任务嵌套异步任务运行结果是一样的,区别在于2上面在同步任务,这个是在异步任务里,一个马上执行,一个不确定。

9.串行队列里异步任务嵌套同步任务


这个很简答,先走1还是先走结束都是不确定的,但我们再结束前加了一个主线程休眠,那么只会先走1,走完1之后又会向队列里加入一个异步任务,所以2什么时候执行也是不确定的,在这里加了主线程休眠,所以2还是在结束之前执行。

10.串行队列里异步任务嵌套异步任务


串行队列的特点导致就算是多个异步任务也只开启一个线程,因为不管开启几个都是顺序执行,开多了反而浪费资源,就酱。

11.串行队列里同步任务嵌套同步任务


这个组合就有意思,直接崩了。这里需要好好分析一下,首先调用dispatch_sync函数将block添加到queue这个串行队列的最后面,由于是同步任务,所以会立刻执行这个block,然后在这个block里面又调用一个dispatch_sync函数将另一个block添加到queue这个队列的最后面,由于是同步任务,所以会立刻执行这个block,但这是一个串行队列,要想执行后面的blcok需要前面的dispatch_sync函数先返回,但dispatch_sync函数要想返回需要执行完这个block,这就导致了两个任务相互等待,造成死锁。

12.延迟执行

 dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0/*延迟执行时间*/ * NSEC_PER_SEC));
   
            dispatch_after(delayTime, dispatch_get_main_queue(), ^{
                NSLog(@"延迟执行");
            });

13.定时器


14.group之同步任务


通过group可以监听一组任务是否都完成,完成了会自动回调 dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^

        {

            // 完成

            NSLog(@"over");

        });

没个任务都是在分线程中执行的,不占用主线程资源,适用于处理一下复杂的操作,当所有任务结束之后,回调主线程刷新数据。如果里面再添加异步任务,这时候就失效了。

15.group之异步任务

上面说了如果group里面又添加了异步任务,那么上面的机制就不气作用的,如果想要实现同样的功能需要这样做


加一对dispatch_group_enter(group),dispatch_group_leave(group);这样就可以了。

16.apply

如果我们写一个for循环


结束是先执行的,如果我们想要for循环执行完之后再执行结束,那可以这样做


17.barrier(栅栏)


栅栏的就像一个分割线,前面的任务执行完才能执行后面的任务。


18.信号量


信号量在多线程开发中被广泛使用,当一个线程在进入一段关键代码之前,线程必须获取一个信号量,一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待前面的线程释放信号量。

    信号量的具体做法是:当信号计数大于0时,每条进来的线程使计数减1,直到变为0,变为0后其他的线程将进不来,处于等待状态;执行完任务的线程释放信号,使计数加1,如此循环下去。


最后附上一张各种线程锁的效率排行。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,265评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,274评论 1 288
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,087评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,479评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,782评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,218评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,594评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,316评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,955评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,274评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,803评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,177评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,732评论 3 229
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,953评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,687评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,263评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,189评论 2 258