GCD-并发队列/串行队列,同步/异步

学多线程时,不注意总结老是学学忘忘,今天特地总结下。只为总结留作资料,参考了许多博客内容,如有博主不爽请留言,立马删除

队列

GCD的队列可以分为2大类型

并发队列(Concurrent Dispatch Queue):

并行队列是指队列中的任务可以并发地执行,即开始执行队首的任务后,不必等其执行完毕就可以接着开始执行队首之后的任务,因此在某一时刻可能存在同时执行的多个任务(使用多个多个线程)。

串行队列(Serial Dispatch Queue)

串行队列是指队列中的任务是一个接一个地执行的,队首的任务执行完毕后才能执行其后面的任务,直至执行队尾的任务(使用一个线程)

0FBC2146-4845-4063-82D2-6E64BA61F236.png

代码:

    dispatch_async(queue, ^{
        NSLog(@"0");
    });
    dispatch_async(queue, ^{
        NSLog(@"1");
    });
    dispatch_async(queue, ^{
        NSLog(@"2");
    });
    dispatch_async(queue, ^{
        NSLog(@"3");
    });
    dispatch_async(queue, ^{
        NSLog(@"4");
    });
    dispatch_async(queue, ^{
        NSLog(@"5");
    });
    dispatch_async(queue, ^{
        NSLog(@"6");
    });
    dispatch_async(queue, ^{
        NSLog(@"7");
    });
    dispatch_async(queue, ^{
        NSLog(@"8");
    });
    dispatch_async(queue, ^{
        NSLog(@"9");
    });

如果queue是Concurrent Dispatch Queue时,不用等当前正在执行的任务处理结束。首先执行任务0,不管任务0的执行是否结束都开始执行任务1,如此反复。并且不一定哪个先执行完成,所以打印结果是乱序。
打印结果:

2016-08-20 16:59:27.630 GCDDemo[8064:888741] 2
2016-08-20 16:59:27.630 GCDDemo[8064:888756] 1
2016-08-20 16:59:27.630 GCDDemo[8064:888739] 0
2016-08-20 16:59:27.630 GCDDemo[8064:888738] 3
2016-08-20 16:59:27.631 GCDDemo[8064:888791] 4
2016-08-20 16:59:27.632 GCDDemo[8064:888741] 6
2016-08-20 16:59:27.632 GCDDemo[8064:888792] 5
2016-08-20 16:59:27.632 GCDDemo[8064:888793] 7
2016-08-20 16:59:27.632 GCDDemo[8064:888756] 8
2016-08-20 16:59:27.632 GCDDemo[8064:888794] 9

如果queue是Serial Dispatch Queue时,任务挨个执行,任务0执行结束,接着执行任务1,如此反复。打印结果一定是有顺序的
打印结果为:

2016-08-20 17:07:25.717 GCDDemo[8093:897228] 0
2016-08-20 17:07:25.717 GCDDemo[8093:897228] 1
2016-08-20 17:07:25.718 GCDDemo[8093:897228] 2
2016-08-20 17:07:25.718 GCDDemo[8093:897228] 3
2016-08-20 17:07:25.718 GCDDemo[8093:897228] 4
2016-08-20 17:07:25.718 GCDDemo[8093:897228] 5
2016-08-20 17:07:25.718 GCDDemo[8093:897228] 6
2016-08-20 17:07:25.719 GCDDemo[8093:897228] 7
2016-08-20 17:07:25.719 GCDDemo[8093:897228] 8
2016-08-20 17:07:25.719 GCDDemo[8093:897228] 9

创建方式:

并发队列(Concurrent Dispatch Queue):

(1)GCD默认已经提供了全局的并发队列,供整个应用使用,获取方式:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

第二个参数是为了以后扩展使用的,现在你只需要往里传入0。,第一个参数为优先级,全局并发队列的优先级有四个

#define DISPATCH_QUEUE_PRIORITY_HIGH 2 //高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台

你可以通过传递DISPATCH_QUEUE_PRIORITY_HIGH和DISPATCH_QUEUE_PRIORITY_LOW常量来分别获取高和低优先级的队列。如你所料,高优先级并发队列中的任务要在默认和低优先级队列中的任务之前执行。同样的,在默认优先级队列中的任务要在低优先级队列中的任务之前执行。

(2)用dispatch_queue_create函数创建

dispatch_queue_t queue = dispatch_queue_create("com.private.ConcurrentQueue",DISPATCH_QUEUE_CONCURRENT);

第一个参数为队列名称,第二个参数为队列类型(串行和并发):

DISPATCH_QUEUE_CONCURRENT //并发队列
DISPATCH_QUEUE_SERIAL // 串行队列,和填入NULL等价

串行队列(Serial Dispatch Queue)

(1)主队列是GCD自带的一种特殊的串行队列,放在主队列中的任务,都会放到主线程中执行

使用dispatch_get_main_queue()获得主队列

dispatch_queue_t queue = dispatch_get_main_queue();

(2)使用dispatch_queue_create函数创建

dispatch_queue_t queue = dispatch_queue_create("com.private.SerialQueue", DISPATCH_QUEUE_SERIAL);

同步/异步

同步和异步是针对当前代码流(即当前线程)和加入队列中的任务之间执行顺序的关系而言的。以同步的方式向队列中添加任务会阻塞当前线程,直到同步到队列中的任务执行完毕返回后,才会接着执行当前的代码流;以异步的方式向队列中添加的任务则不会阻塞当前线程,将任务添加到队列中后,不用等待任务执行完毕,即刻执行当前代码流。

同步(dispatch_sync):

dispatch_sync(myQueue,^{ printf("1"); //任务 1 });
printf("2"); 
dispatch_sync(myQueue,^{ printf("3"); //任务 3 });
printf("4");

上面的代码执行结果只有一种可能,即输出“1234”。

在将输出 1 的任务(即代码中任务 1)同步到队列 myQueue 中后,当前线程阻塞,等待任务 1 执行完毕并返回后(即输出 1 之后),才能接着执行当前线程,输出 2。输出 2 之后,当前代码流继续运行,将任务 3 再同步到队列 myQueue 中后,当前线程阻塞,等待任务 3 执行,输出 3,之后当前代码流继续运行输出 4。

这段代码的输出结果与 myQueue 是串行队列还是并行队列没有关系。
异步(dispatch_async):

dispatch_async(serialQueue,^{ printf("1"); //任务 1 }); 
printf("2"); 
dispatch_async(serialQueue,^{ printf("3"); //任务 3 }); 
printf("4");

上面代码执行结果可能为 “1234”、“1243”、“2134”、“2143”、“2413” 中的一种,2 始终在 4 前面,1 始终在 3 前面(注意:此例中的队列(serialQueue)为串行队列,串行队列的概念将在后文讲述),2 始终在 3 前面。

将任务 1 异步添加到队列 serialQueue 中之后,不需要等待其执行完毕,当前代码流就继续执行了。当前代码流输出 2 时,可能任务 1 还没执行,也可能执行完毕了,因此 1 可能在 2 前输出也可能在 2 后输出;

同理,将任务 3 异步添加到队列 serialQueue 中之后,不需要等待其执行完毕,当前代码流就继续执行。当前代码流输出 4 时,可能任务 3 还没执行,也可能执行完毕了,因此 3 可能在 4 前输出也可能在 4 后输出。

对于当前代码流,输出 2 一定在 输出 4 前执行,因此 2 必定在 4 前输出。

对于串行队列 serialQueue ,任务 1 一定在 任务 3 前执行,因此 1 必定在 3 前输出。

将任务 3 添加到队列 serialQueue 的操作必定在输出 2 后进行,因此 2 必定在 3 前输出。

总结:
串行队列里的任务不能并发执行,只能一个接一个地执行,同一时刻该串行队列里的任务最多只有一个在执行;并发队列里的任务后面的任务不必等待前面的任务执行完毕再执行,可以多个同时执行,同一时刻该并行队列里的任务可以有多个正在执行。
同步异步描述的是当前线程或代码流是否要阻塞以等待加入队列的任务执行完毕:同步要阻塞当前线程;异步不会阻塞当前线程。

参考:
http://www.cnblogs.com/wendingding/p/3806821.html
http://huuang.com/?p=83
《Objective-C高级编程 iOS与OS X多线程和内存管理》

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

推荐阅读更多精彩内容

  • 从哪说起呢? 单纯讲多线程编程真的不知道从哪下嘴。。 不如我直接引用一个最简单的问题,以这个作为切入点好了 在ma...
    Mr_Baymax阅读 2,726评论 1 17
  • 背景 担心了两周的我终于轮到去医院做胃镜检查了!去的时候我都想好了最坏的可能(胃癌),之前在网上查的症状都很相似。...
    Dely阅读 9,226评论 21 42
  • 现在iOS的多线程方案主要有以下这几种: GCD(Grand Central Dispatch):使用dispat...
    寒光冷剑阅读 1,536评论 0 2
  • iOS 多线程系列 -- 基础概述iOS 多线程系列 -- pthreadiOS 多线程系列 -- NSThrea...
    shannoon阅读 827评论 0 2
  • 那年我第二次高考失利,在当时考不上大学就不会在念书了。上学时,别的同学喜欢金庸古龙梁羽生。而我却喜欢在饭后看一点爱...
    冶梦阅读 247评论 0 0