GCD

GCD 的一些简介

  • 什么是GCD:
    1.GCD 全称是Grand Central Dispatch, 可以译为“牛逼的中枢调度器”,并不是多线程技术
    2.纯C语言,提供了非常多的强大的函数
  • GCD的优势
    1.GCD是苹果公司为多核的并行运算提出的解决方案
    2.GCD会自动利用更多的CPU内核(比如双核、四核)
    3.GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
    4.程序员只需告诉GCD想要执行什么任务,不需要编写任何线程管理代码

GCD 的队列(四种)

  • 串行队列
    dispatch_queue_t q = dispatch_queue_create("threadname", NULL);

  • 并行队列
    dispatch_queue_t q = dispatch_queue_create("threadname", DISPATCH_QUEUE_CONCURRENT);

  • 全局队列
    dispatch_queue_t q = dispatch_get_global_queue(0, 0);

  • 主队列
    dispatch_queue_t q = dispatch_get_main_queue();

    • 全局队列 & 并发队列
      1> 名称,并发队列取名字,适合于企业开发跟踪错误
      2> release,在MRC 并发队列 需要使用的
      dispatch_release(q);//ARC 情况下不需要release !
    • 全局队列 & 串行队列
      全局队列: 并发,能够调度多个线程,执行效率高
      - 费电
      串行队列:一个一个执行,执行效率低
      - 省点
    • 判断依据:用户上网方式
      - WIFI : 可以多开线程
      - 流量 : 尽量少开线程

GCD 队列任务常见代码

1.串行队列,同步任务

/**
*   不会开启线程,会顺序执行
*/
-(void)gcdDemo1{
    //1.队列 - 串行
    /**
     1.队列名称:
     2.队列的属性: DISPATCH_QUEUE_SERIAL 标示串行!
     */
    dispatch_queue_t q = dispatch_queue_create("thread1", NULL);
    
    //2.同步执行任务
    for (int i = 0; i < 10; i++) {
        dispatch_sync(q, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

2.串行队列,异步任务

-(void)gcdDemo2{
    /**
     会开几条线程?会顺序执行吗?
     */
    //1.队列 - 串行
    dispatch_queue_t q = dispatch_queue_create("thread1", NULL);
    
    //2.异步执行任务
    for (int i = 0; i < 10; i++) {
        NSLog(@"%d------------",i);
        dispatch_async(q, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
    //哥么在主线程!
    NSLog(@"come here");
}

3.并发队列,异步执行

-(void)gcdDemo3{
    //1.队列 - 并发 DISPATCH_QUEUE_CONCURRENT
    dispatch_queue_t q = dispatch_queue_create("thread1", DISPATCH_QUEUE_CONCURRENT);
    
    //2.异步执行任务
    for (int i = 0; i < 10; i++) {
        dispatch_async(q, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
    //哥么在主线程!
    NSLog(@"come here");
}

4.并发队列,同步执行

和 串行队列,同步执行 效果一样!

-(void)gcdDemo4{
    
    //1.队列 - 并发 DISPATCH_QUEUE_CONCURRENT
    dispatch_queue_t q = dispatch_queue_create("thread1", DISPATCH_QUEUE_CONCURRENT);
    
    //2.同步执行任务
    for (int i = 0; i < 10; i++) {
        dispatch_sync(q, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
    //哥么在主线程!
    NSLog(@"come here");
}

GCD同步任务的作用-- 处理任务之间的依赖关系

在开发中,通常会将耗时操作放后台执行,有的时候,有些任务彼此有"依赖"关系!

例子: 登录,支付,下载

利用同步任务,能够做到任务依赖关系,前一个任务是同步任务,哥么不执行完,队列就不会调度后面的任务

-(void)gcdDemo5{
    dispatch_queue_t loginQueue = dispatch_queue_create("thread1", DISPATCH_QUEUE_CONCURRENT);
    //1.用户登录
    dispatch_sync(loginQueue, ^{
        NSLog(@"用户登录  %@",[NSThread currentThread]);
    });
    
    //2.支付
    dispatch_async(loginQueue, ^{
        NSLog(@"支付  %@",[NSThread currentThread]);
    });
    //3.下载
    dispatch_async(loginQueue, ^{
        NSLog(@"下载  %@",[NSThread currentThread]);
    });
}
  • 增强版同步任务

可以队列调度多个任务前,指定一个同步任务,让所有的异步任务,等待同步任务执行完成,这就是依赖关系

  • 同步任务,会造成一个死锁!
-(void)gcdDemo6{
    //队里
    dispatch_queue_t q = dispatch_queue_create("thread1", DISPATCH_QUEUE_CONCURRENT);
    //任务
    void (^task)()=^{
        for (int i = 0; i < 10; i++) {
            NSLog(@"%d   %@",i ,[NSThread currentThread]);
        }
        //1.用户登录
        dispatch_sync(q, ^{
            NSLog(@"用户登录  %@",[NSThread currentThread]);
        });
        //2.支付
        dispatch_async(q, ^{
            NSLog(@"支付  %@",[NSThread currentThread]);
        });
        //3.下载
        dispatch_async(q, ^{
            NSLog(@"下载  %@",[NSThread currentThread]);
        });
        
       
    };
    dispatch_async(q, task);
}

GCD 主队列 死锁问题

  • 死锁版
// 主队列,同步任务
//阻塞主线程!!
-(void)gcdDemo2{
    //1.队列  -> 一启动就有主线程,主队列只需要获取
    dispatch_queue_t q = dispatch_get_main_queue();
    NSLog(@"这里!!");
    //2.同步任务 -----> 死锁
    dispatch_sync(q, ^{
        NSLog(@"能来吗?");
    });
    NSLog(@"come here -- %@",[NSThread currentThread]);
}
  • 不死锁版
//MARK: 主队列同步任务(增强版--不死锁)
-(void)gcdDemo3{
    void (^task)() = ^{
        //1.队列  -> 一启动就有主线程,主队列只需要获取
        dispatch_queue_t q = dispatch_get_main_queue();
        NSLog(@"这里!!");
        //2.同步任务
        dispatch_sync(q, ^{
            NSLog(@"睡会");
            [NSThread sleepForTimeInterval:1.0];
            NSLog(@"能来吗?");
        });
        NSLog(@"come here -- %@",[NSThread currentThread]);
    };
    //全局队列,异步任务
    dispatch_async(dispatch_get_global_queue(0, 0), task);
}

线程间通信式例

-(void)gcdDemo{
    //指定任务执行方法 -- 异步
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
     
        //更新UI 主队列,就是专门负责在主线程上调度任务的队列!
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"更新UI%@",[NSThread currentThread]);
        });
    });
}

GCD 一次性代码

  • 有的时候,我们在开发中,有些代码,从程序启动之后,就只希望执行一次,
    尤其在使用单例设计的时候,使用GCD来让代码一次执行的情况,非常多!
    面试非常流行,手写GCD的单例!
-(void)once{
    //GCD提供了一个一次执行的机制,不仅能够保证只会被执行一次.而且是线程安全的!
    //GCD-Once 内部是会加锁!! 但是 比普通的互斥锁 效率高 100多倍 苹果推荐使用这个
    static dispatch_once_t onceToken;
    NSLog(@"%ld",onceToken);
    dispatch_once(&onceToken, ^{
        //只会执行一次的代码
        NSLog(@"执行了!!--%@",[NSThread currentThread]);
    });
    
}

调度组

-(void)group1{
    //1.队列
    dispatch_queue_t q = dispatch_get_global_queue(0, 0);
    //2.调度组
    dispatch_group_t g = dispatch_group_create();
    //3.添加任务,让队列执行,任务执行情况最终通知组
    dispatch_group_async(g, q, ^{
        NSLog(@"download A %@",[NSThread currentThread]);
    });
    dispatch_group_async(g, q, ^{
        [NSThread sleepForTimeInterval:1.0];
        NSLog(@"download B %@",[NSThread currentThread]);
    });
    dispatch_group_async(g, q, ^{
        [NSThread sleepForTimeInterval:0.8];
        NSLog(@"download C %@",[NSThread currentThread]);
    });
    //4. 所有任务执行完毕后,获得通知
    //用一个调度组,可以监听全局队列调度的任务,执行完毕之后,在主队列执行最终处理!
    //dispatch_group_notify 本身是异步的
    dispatch_group_notify(g, dispatch_get_main_queue(), ^{
        //更新UI,通知用户
        NSLog(@"OK  %@",[NSThread currentThread]);
    });
    
    NSLog(@"come here");
    
}

全局队列参数

//全局队列
    /* 参数
     1. 涉及到系统适配
     iOS 8   服务质量
     QOS_CLASS_USER_INTERACTIVE    用户交互(希望线程快速被执行,不要用好使的操作)
     QOS_CLASS_USER_INITIATED      用户需要的(同样不要使用耗时操作)
     QOS_CLASS_DEFAULT             默认的(给系统来重置队列的)
     QOS_CLASS_UTILITY             使用工具(用来做耗时操作)
     QOS_CLASS_BACKGROUND          后台
     QOS_CLASS_UNSPECIFIED         没有指定优先级
     iOS 7  调度的优先级
     - DISPATCH_QUEUE_PRIORITY_HIGH 2               高优先级
     - DISPATCH_QUEUE_PRIORITY_DEFAULT 0            默认优先级
     - DISPATCH_QUEUE_PRIORITY_LOW (-2)             低优先级
     - DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN 后台优先级
     
     提示:尤其不要选择BACKGROUND 优先级,服务质量,线程执行会慢到令人发指!!!
     
     
     2. 为未来使用的一个保留,现在始终给0.
     
     老项目中,一般还是没有淘汰iOS 7  ,没法使用服务质量
     */

GCD 总结

GCD 核心概念:将任务添加到队列,指定任务执行的方法

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

推荐阅读更多精彩内容