iOS线程②GCD

GCD的基本概念

  • 1.GCD和NSThread的区别,GCD不需要程序员管理线程的生命周期,NSThread需要程序员手动管理生命周期

  • 2.学习GCD之前需要先弄清一些概念

    • 任务:执行什么样的操作
    • 队列:用来存放任务
      • 因为GCD不用程序员管理线程的声明周期,因此可以不管线程的创建和销毁
  • 3.GCD的使用步骤

    • 1.定制任务:确认想做的事情
    • 2.将任务添加到队列中:GCD会自动将队列中的任务取出,放到对应的线程中执行
      • 任务的取出遵循队列的FIFO原则:先进先出,后进后出。(这里需要和栈区分开来,栈是先进后出,因为,栈只有一个出口)
  • 4.GCD中的任务

    • GCD中有两个用来执行任务的常用函数
      • 同步方式执行任务
        • dispatch_sync(dispatch_queue_t _Nonnull queue, <^(void)block>)
      • 异步方式执行任务
        • dispatch_async(dispatch_queue_t _Nonnull queue, <^(void)block>)
    • 同步和异步的区别
      • 同步:只能在当前线程中执行任务,不具备开线程的能力
      • 异步:可以在新的线程中执行任务,具备开启新线程的能力
  • 5.GCD队列的类型

    • 并发队列(Concurrent Dispatch Queue)
      • 可以让多个任务并发(同时)执行,自动开启多个线程同时执行任务
      • 并发功能再有在异步 (dispatch_async)函数下才有效
    • 串行队列(Serial Dispatch Queue)
      • 让任务一个接着一个地执行,一个任务执行完毕后,再执行下一个任务
  • 6.GCD任务和队列代码详述


@interface ViewController ()

@end

@implementation ViewController

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self globlQueueAsyncCoucurrent];
}
//异步函数+串行队列:会开线程,开一条线程,队列中的任务是串行执行
-(void)asyncConcurrent
{
    //1.创建队列
    
  /**
   const char *_Nullable label:C语言字符串,线程的标签
   dispatch_queue_attr_t _Nullable attr:队列的类型
        DISPATCH_QUEUE_CONCURRENT:并发
        DISPATCH_QUEUE_SERIAL:串行
   */
  dispatch_queue_t asyncQueue =   dispatch_queue_create("lxc", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(asyncQueue, ^{
        NSLog(@"queue1---%@",[NSThread currentThread]);
    });
    //2.封装任务->添加任务到队列中
    /**
     dispatch_queue_t queue:队列是哪个
     dispatch_block_t block:block参数
     */
    dispatch_async(asyncQueue, ^{
        NSLog(@"queue2---%@",[NSThread currentThread]);
    });
    dispatch_async(asyncQueue, ^{
        NSLog(@"queue3---%@",[NSThread currentThread]);
    });
    dispatch_async(asyncQueue, ^{
        NSLog(@"queue4---%@",[NSThread currentThread]);
    });
    NSLog(@"----end----");
    //线程没有顺序
}
//异步函数+串行队列:会一条开线程,队列中的任务是串行执行
-(void)asyncSerial
{
    dispatch_queue_t asyncQueue =  dispatch_queue_create("cyf", DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(asyncQueue, ^{
        NSLog(@"queue1---%@",[NSThread currentThread]);
    });
    dispatch_async(asyncQueue, ^{
        NSLog(@"queue2---%@",[NSThread currentThread]);
    });
    dispatch_async(asyncQueue, ^{
        NSLog(@"queue3---%@",[NSThread currentThread]);
    });
    dispatch_async(asyncQueue, ^{
        NSLog(@"queue4---%@",[NSThread currentThread]);
    });
    NSLog(@"----end----");
    
}
//同步函数+并行队列:不会开启线程,所有任务都在主线程中执行,队列中的任务是并行执行
-(void)syncConcurent
{
    dispatch_queue_t syncQueue =  dispatch_queue_create("23", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(syncQueue, ^{
        NSLog(@"syncQueue1----%@",[NSThread currentThread]);
    });
    dispatch_sync(syncQueue, ^{
        NSLog(@"syncQueue2----%@",[NSThread currentThread]);
    });
    dispatch_sync(syncQueue, ^{
        NSLog(@"syncQueue3----%@",[NSThread currentThread]);
    });
    dispatch_sync(syncQueue, ^{
        NSLog(@"syncQueue4----%@",[NSThread currentThread]);
    });
}
//同步函数+串行队列:不会开启线程,所有的任务都在主线程中执行,队列中的任务是串行执行
-(void)syncSerial
{
    dispatch_queue_t syncQueue = dispatch_queue_create("22", DISPATCH_QUEUE_SERIAL);
    
    dispatch_sync(syncQueue, ^{
        NSLog(@"syncQueue1----%@",[NSThread currentThread]);
    });
    dispatch_sync(syncQueue, ^{
        NSLog(@"syncQueue2----%@",[NSThread currentThread]);
    });
    dispatch_sync(syncQueue, ^{
        NSLog(@"syncQueue3----%@",[NSThread currentThread]);
    });
    dispatch_sync(syncQueue, ^{
        NSLog(@"syncQueue4----%@",[NSThread currentThread]);
    });
    NSLog(@"---end---");
}
//全局并发队列+并发:不会创建线程,会从GCD本身就有全局并发队列,只是拿出,并且创建多少线程不受控制
-(void)globlQueueAsyncCoucurrent
{
    
    /*
     //获得全局并发队列:
    第一个参数:队列的优先级
        DISPATCH_QUEUE_PRIORITY_DEFAULT 默认 0
        DISPATCH_QUEUE_PRIORITY_HIGH 最高    2
        DISPATCH_QUEUE_PRIORITY_BACKGROUND 最低优先级 -1
        DISPATCH_QUEUE_PRIORITY_LOW 低优先级  1
     第二个参数:传0即可
     */
    //获得全局并发队列,这个队列本身是存在的,在GCD中本身就有全局并发队列,只是拿过来用一下,需要注意的是全局并发队列,是不受控制的,并不是有多少任务就先多少线程
   dispatch_queue_t globlQueue =  dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(globlQueue, ^{
        NSLog(@"asyncQueue1----%@",[NSThread currentThread]);
    });
    dispatch_async(globlQueue, ^{
        NSLog(@"asyncQueue2----%@",[NSThread currentThread]);
    });
    dispatch_async(globlQueue, ^{
        NSLog(@"asyncQueue3----%@",[NSThread currentThread]);
    });
    dispatch_async(globlQueue, ^{
        NSLog(@"asyncQueue4----%@",[NSThread currentThread]);
    });
    //全局并发队列没有顺序
}
@end

  • 7.GCD的常用函数

    • 定时任务和单例函数
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
    /**
     *  @param DISPATCH_TIME_NOW 从现在开始计算时间
     *  @param int64_t 延迟的时间 2.0 GCD时间单位:纳秒
     *  @dispatch_get_main_queue 队列 
     CGD的定时任务可以控制几秒后再那个线程中执行
     */
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), queue, ^{
        NSLog(@"-----GCD------%@",[NSThread currentThread]);
    });
    //一次性代码
    //不能放在懒加载中的,应用场景:单例模式
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"---once----");
    });
- ##### 栅栏函数
    dispatch_queue_t queue = dispatch_queue_create("download", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"download1-----%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"download2-----%@",[NSThread currentThread]);
    });
    /**
     *  GCD栅栏函数
        该函数可以控制多线程异步的执行顺序(哪个先执行哪个后执行)
        注意:在使用栅栏函数的时候不可以使用全局并发队列
     */
    dispatch_barrier_async(queue, ^{
        NSLog(@"+++++++++++++++");
    });
    dispatch_async(queue, ^{
        NSLog(@"download4-----%@",[NSThread currentThread]);
    });
  • 遍历函数
         @param 10 迭代的次数
         @param 队列(并发队列)
         @param index 索引

         @return
         
        dispatch_apply(10, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
            NSLog(@"%zd-----%@",index,[NSThread currentThread]);
            
  • GCD队列组函数
    • 队列组
      • 如果有这么一种需求,首先分别异步执行2个耗时操作,其次等2个异步操作都执行完毕后,再回到主线程执行操作。如果遇到这种业务可以考虑用队列组实现
//1.创建队列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    //2.创建队列组
    dispatch_group_t group =  dispatch_group_create();
    //3.队列组函数
    /**
     1.封装任务
     2.把任务添加到队列中
     3.会监听任务的执行情况,通知group
     */
    dispatch_group_async(group, queue, ^{
        NSLog(@"1----%@",[NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"2----%@",[NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"3----%@",[NSThread currentThread]);
    });
    
    //监听通知,当队列组中所有的任务都执行完毕的时候,进入到下面的方法
    /**
     *  监听通知的时候函数不会阻塞,内部本身是异步的
     */
  dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        
       NSLog(@"end---%@",[NSThread currentThread]);
    });
    /**
     监听通知的另一个函数,这个函数会一直等待,死等。直到队列组中所有的任务都执行完毕之后才能执行,内部本身是同步的
     */
    dispatch_group_wait(group, DISPATCH_TIME_NOW);
    NSLog(@"----end----");
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容