iOS多线程GCD之队列和任务详解(实例代码验证篇)

一、初步了解什么是GCD?

GCD 全称Grand Central Dispatch(队列调度)
是一套低层API,提供了⼀种新的方法来进⾏并发程序编写。从基本功能上讲,GCD有点像NSOperationQueue,他们都允许程序将任务切分为多个单一任务,然后提交⾄⼯作队列来并发的或者串⾏的执行。
GCD是C实现,⽐NSOpertionQueue更底层更高效,并且它不是Cocoa框架的一部分 并发任务会像NSOperationQueue那样基于系统负载来合适地并发进⾏,而串⾏行队列同一时间只执行单一任务。 GCD的API很大程度上基于block

二、GCD如何实现?

GCD主要由队列和任务两部分来实现,许多同学对队列和线程容易搞混,这里把它分类来详述:
1.队列主要包含三种:主线程队列、并行队列、串行队列
2.任务主要包含两种:异步任务和同步任务
多线程执行过程就是把任务放在队列中去执行的过程
(在计算机操作系统中对异步和同步有很深入的概念和定义,并影响到计算机系统有单线程到多线程的过渡发展,其中牵涉到线程切换、时间片等概念。但在GCD这里我们只做大致使用区别)
队列:
并行队列 :在队列中的多个任务(线程) 同时执行 (不按顺序执行)
串行队列: 在队列中的多个任务(线程)排队 依次执行(按顺序执行)

任务:
同步(sync) 和 异步(async) 的主要区别在于会不会阻塞当前线程,直到 Block 中的任务执行完毕!
如果是 同步(sync) 操作,它会阻塞当前线程并等待 Block 中的任务执行完毕,然后当前线程才会继续往下运行。
如果是 异步(async)操作,当前线程会直接往下执行,它不会阻塞当前线程。

好了 ,不理解也没关系,我在代码中给你来说明和验证;

1、队列 (主要三个队列,为更好理解队列,队列中全部先放入异步任务)

1.主线程队列

主线程队列 内部执行任务是串行的同步操作
主线程队列不需要我们创建,通过dispatch_get_main_queue()方法获得

    dispatch_queue_t  queue = dispatch_get_main_queue();
    dispatch_async(queue, ^{

    });
  或者
    dispatch_async(dispatch_get_main_queue(), ^{

    });

实例:

-(void)mainQueue{
      //异步任务
        dispatch_async(dispatch_get_main_queue(), ^{
            for (NSInteger i = 0; i < 10; i++) {
                NSLog(@"主线程任务2_i:%ld",i);
            }
        });
}

实例输出:

Snip20161012_2.png

小结:数据在主线程中按顺序输出

2.创建串行队列

// 创建一个用户串行队列 dispatch_queue_create("com.gcd", NULL),"com.gcd":队列名是一个C字符串,没有特别的要求,Apple建议用倒装的标识符来表示  
//串行队列内部也是串行操作
    dispatch_async( dispatch_queue_create("com.gcd", NULL), ^{
          //任务
      });
     // 我们自己创建的队列,我们需要自己销毁(非arc  需要销毁)
      //dispatch_release(queue);

实例:

-(void)tandemPrivateQueue{
    //自定义私有串行队列
    dispatch_queue_t queue=dispatch_queue_create("com.privateQueue", NULL);

    //异步任务1加入队列中
    dispatch_async(queue, ^{
        NSLog(@"私有队列任务1");
        for (NSInteger i = 0; i < 10; i++) {
            NSLog(@"私有队列任务1_i:%ld",i);
        }     
    });
    //异步任务2加入队列中
    dispatch_async(queue, ^{
        NSLog(@"私有队列任务2");
        for (NSInteger i = 0; i < 10; i++) {
            NSLog(@"私有队列任务2_i:%ld",i);
        }
        
    });
    
}

实例输出:

Snip20161012_3.png

小结:私有队列中任务是串行 如输出显示: 先执行任务1完成后->再执行任务2

3.全局队列 并行队列

    /*
    // 并行队列(全局)不需要我们创建,通过dispatch_get_global_queue()方法获得
    // 三个可用队列
    // 第一个参数是选取按个全局队列,一般采用DEFAULT,默认优先级队列
    // 第二个参数是保留标志,目前的版本没有任何用处(不代表以后版本),直接设置为0就可以了
    // DISPATCH_QUEUE_PRIORITY_HIGH
    //DISPATCH_QUEUE_PRIORITY_DEFAULT
    // DISPATCH_QUEUE_PRIORITY_LOW
    */
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

实例:

-(void)parallelGlobalQueue{
    //全局并行队列
    dispatch_queue_t globalQueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_async(globalQueue, ^{
        NSLog(@"全局队列任务1");
        for (NSInteger i = 0; i < 10; i++) {
            NSLog(@"全局队列任务1_i:%ld",i);
            [NSThread sleepForTimeInterval:0.5];
        }
    });
    dispatch_async(globalQueue, ^{
        NSLog(@"全局队列任务2");
        for (NSInteger i = 0; i < 10; i++) {
            NSLog(@"全局队列任务2_i:%ld",i);
            [NSThread sleepForTimeInterval:0.5];
        }
    });
}

示例输入:

Snip20161012_4.png

小结:全局队列中任务是异步同时进行的:任务1和2同时进行

队列到这你该大致明白了 下面再来搞定任务

2、任务

//同步任务:
  dispatch_sync(, ^{
      //code here
      NSLog(@"%@", [NSThread currentThread]);
  });
//异步任务:
  dispatch_async(, ^{
      //code here
      NSLog(@"%@", [NSThread currentThread]);
  });

同步和异步任务的区别
在上文中队列讲解中所有队列中任务都是异步任务,下面我们在globalQueue队列 把1、2两个异步任务改成同步任务呢,如下面修改 会出现什么情况?

-(void)parallelGlobalQueue{
    //并行全局队列
    dispatch_queue_t globalQueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //添加一个同步任务1
     dispatch_sync(globalQueue, ^{
        NSLog(@"全局队列任务1");
        for (NSInteger i = 0; i < 10; i++) {
            NSLog(@"全局队列任务1_i:%ld",i);
        }
    });
    //添加一个同步任务2
     dispatch_sync(globalQueue, ^{
        NSLog(@"全局队列任务2");
        for (NSInteger i = 0; i < 10; i++) {
            NSLog(@"全局队列任务2_i:%ld",i);
        }
    });
}

输出:

Snip20161012_6.png

小结:同是在并行globalQueue队列 通过同步任务和异步任务输出对为什么不同呢?
原因:1和2两个是同步任务,虽然两个任务在并行队列中同时进行,但由同步的原因 任务1会执行完block中所有代码才会继续执行下面的代码,同理任务2也是,就是出现了任务1 输出0-9后才输出任务2。
在此,你明白了异步和同步的区别了吗?
如果是 同步(sync) 操作,它会阻塞当前线程并等待 Block 中的任务执行完毕,然后当前线程才会继续往下运行。
如果是 异步(async)操作,当前线程会直接往下执行,它不会阻塞当前线程。

关于异步和同步对UI的影响

我们不妨在Main.storyboard中放一个label 看看启动效果即知

Snip20161012_11.png

同步任务 会在串/并队列中1、2任务完成输出后显示UIlabel"启动页";
而异步任务 会在串/并队列 先显示出来 在执行1、2任务输出0-9;
可以看出 同步会阻碍主线程的进行,异步不会,所以在许多耗时的操作中放在异步任务来完成后,再返回主线程进行刷新UI

至于队列对UI的影响

这样说吧队列只装载任务并管理任务的顺序,是同时来或一个一个来,有没有影响由队列中任务来决定;但是有种情况也会特殊

-(void)tandemPrivateQueue{
    //自定义私有串行队列
    dispatch_queue_t queue=dispatch_queue_create("com.privateQueue", NULL);

    //异步任务1加入私有队列中
    dispatch_async(queue, ^{
        NSLog(@"私有队列任务1");
        for (NSInteger i = 0; i < 10; i++) {
            NSLog(@"私有队列任务1_i:%ld",i);
        }
    });
    //同步任务2加入私有队列中
    dispatch_sync(queue, ^{
        NSLog(@"私有队列任务2");
        for (NSInteger i = 0; i < 10; i++) {
            NSLog(@"私有队列任务2_i:%ld",i);
        }
        
    });
    
}

虽然任务1是异步不影响"启动页"的出现,但是如果任务2是同步,"启动页" 会在同步任务2输出完成后方才出现;
这种现象在并行队列中也是如此。

所以不论在串行队列还是并行队列只要有同步任务的出现都会执行完block中代码才会接着往下进行。

总结:到此,就全部结束了!至于队列中嵌套队列,还是任务在嵌套任务,都是万变不离其宗,把基本理解,一起迎刃而解!最后希望和大家一起进步学习!_

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

推荐阅读更多精彩内容

  • 从哪说起呢? 单纯讲多线程编程真的不知道从哪下嘴。。 不如我直接引用一个最简单的问题,以这个作为切入点好了 在ma...
    Mr_Baymax阅读 2,731评论 1 17
  • 本文首发于我的个人博客:「程序员充电站」[https://itcharge.cn]文章链接:「传送门」[https...
    ITCharge阅读 347,207评论 308 1,924
  • 1. GCD简介 什么是GCD呢?我们先来看看百度百科的解释简单了解下概念 引自百度百科:Grand Centra...
    千寻_544f阅读 359评论 0 0
  • 多线程 在iOS开发中为提高程序的运行效率会将比较耗时的操作放在子线程中执行,iOS系统进程默认启动一个主线程,用...
    郭豪豪阅读 2,586评论 0 4
  • 1. GCD简介 iOS开发中多线程的API主要有pthread,NSThread,NSOperation和GCD...
    安东_Ace阅读 1,249评论 0 6