Gcd

2016-07-29  本文已影响0人  ZealPenK

一.GCD基础概念:{

1 .概念:Grand Central Dispatch,纯C语言的,提供了很多非常强大的函数;
2 .GCD优势:{
a.GCD为多核运算的并行运算提供解决方案;
b.GCD会自动利用更多的CPU内核(如2核/4核);
c.GCD会自动管理线程的生命周期(创建/调度/销毁);
d.只需告诉GCD做什么任务,不用编写管理代码;}
3 .GCD的核心:'将任务添加到队列'{
a. 任务:执行什么操作;
b. 队列:用来存放任务;}
4 .GCD的使用的两个步骤:{
a .创建任务:确定要做的事情,用Block封装任务;
b .将任务添加到队列中:{
GCD"自动"从队列中将任务取出,放到对应的线程中执行.
任务的去除遵循队列的"FIFO"原则:'先进先出,后进后出'
}}}

二.队列和任务:{

(一).队列:{
1. 串行队列:'DISPATCH_QUEUE_SERIAL'{
- 定义:
dispatch_queue_t queue = dispatch_queue_create("队列标识符", DISPATCH_QUEUE_SERIAL);
- 串行对类让任务"一个一个有序"的执行,一个执行完后,再执行下一个
- 同时只能调度一个任务执行;}
2. 并发队列:'DISPATCH_QUEUE_CONCURRENT'{
- 定义:
dispatch_queue_t queue = dispatch_queue_create("队列标识符", DISPATCH_QUEUE_CONCURRENT);
- 可以让多任务"同时(并发)"执行,自动开启多个线程同时执行多个任务;
- 并发队列的并发功能只有内部的任务是"异步任务"的时候,才有效}}
(二).任务:{
1. 同步执行任务:在'当前线程'中'依次'执行任务{
dispatch_sync(dispatch_queue_t queue,dispatch_block_t block)
- queue:队列
- block:任务}
2. 异步执行任务:'新开线程',在新线程中执行任务{
dispatch_async(dispatch_queue_t queue.dispatch_block_t block);
- queue:队列
- block:任务}}}

三.延时操作:延迟多少纳秒,在哪个队列中调度执行哪个任务{

  1. 函数:dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block)
  2. 参数:{
    a.dispatch_time_t 'when':延迟的时间;
    b.dispatch_queue_t 'queue':执行任务的队列;
    c.dispatch_block_t 'block':线程要执行的任务;}}

四.队列和任务组合{

  1. 串行队列 + 同步任务:{
    a. "没有"开新线程,在当前线程中执行;
    b. 线程内任务"顺序"执行;
    c. "执行完"线程中所有任务后,执行线程中其他任务;}
  2. 串行队列 + 异步任务:{
    a. "新开"一条线程,原因看下一条;
    b. 新线程中前一个任务执行完后执行后一个任务;
    c. 原来线程中的任务异步执 ,"不必"等待新任务执行完;}
  3. 并发队列 + 同步任务:{
    a. "没有"开新线程,在当前线程中执行;
    b. 线程内任务"顺序"执行;
    c. "执行完"线程中所有任务后,执行线程中其他任务;}
  4. 并发队列 + 异步任务:{
    a. 开启"多条"新线程;
    b. 线程内任务"随机"执行;
    c. 线程外任务"异步"执行;}
  5. 总结:{
- 先看任务:如果是同步任务,则不开新线程,任务依次执行,线程内任务执行完后执行线程外任务;

五.主队列:dispatch_get_main_queue(){

1.特点:{
a. 专门用来在主线程上调度任务的队列;
b. 不会开启新线程;
c. 以先进先出的方式,在主线程空闲的时候才会调度队列中的任务在主线程中执行;
d. 如果当前主线程有正在执行的任务,那么无论主队列中当前被添加了什么任务,都不会被调度
e. 主队会随着主程序启动一起创建,只需获取,不用创建;
}
2.组合:{
a. 主队列 + 异步队列:先执行队列外的主线程中的任务,待主线程中任务都执行完了以后再执行队列中的任务;
任务1 -> dispatch_async{dispatch_get_main_queue(),^ (任务2)} ->任务3
执行顺序:任务1 -> 任务3 -> 任务2;
b. 主队列 + 同步任务 = 锁死:
原因分析:主线程在等待同步任务执行完,同步任务中的主队列在等待主线程中的任务执行完毕;
解决办法:将主队列的同步任务放到子线程中(这么作,何必呢?);}}

六.全局队列:dispatch_get_global_queue(0, 0){

  1. 定义:全局并发队列,系统提供的,工作表现和并发队列一致;
  2. 全局队列:并发队列{'比较'
    a. 没有名字:有名字
    b. 无论ARC还是MRC都不需要考虑释放:MRC下需要dispatch_release(q)
    c. "日常开发"中推荐使用:"开发第三方框架"建议使用并发}}

七.GCD应用:{

  1. 建立依赖:同步任务{
    //获取全局队列
    dispatch_queue_t queue = dispatch_get_global_queue(0,0);
    //在全局队列中执行异步任务,防止耗时任务在主线程中执行
    dispatch_async(queue, ^{
    //建立'任务1','任务2','任务3'的依赖关系,1,2,3依次完成
    dispatch_sync(queue, ^{任务1});
    dispatch_sync(queue, ^{任务2});
    ...
    dispatch_sync(queue, ^{任务3});
    //回到主线程刷新UI(使用异步任务,防止卡顿)
    dispatch_async(dispatch_get_main_queue, ^{主线程刷新UI})
    })
    }

  2. 一次性执行:dispatch_once_t{
    内部有一把锁,保证内部代码只执行一次:
    a. 'once用于设计单例模式:'{
    static NetworkTool *instance;
    //敲dispatch_once会有提示
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    instance = [[NetworkTool alloc] init];
    });

    return instance;
    }
    b. '互斥锁单例设计模式:'{
    static AccountManager *manager;

    // 为保证在多线程的环境下,线程的安全,所以添加了一把互斥锁
    // 但是互斥锁的性能有点儿差
    @synchronized(self) {
    // 判断内存中有没有这个对象,如果没有,就创建
    if (manager == nil) {
    manager = [[AccountManager alloc] init];
    }
    }
    return manager;}
    c. 比较:性能once更好,操作更简单;}

  3. 调度组

}

上一篇 下一篇

猜你喜欢

热点阅读