GCD

2018-05-04  本文已影响0人  bland_Xu

GCD 的一些简介

GCD 的队列(四种)

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 一次性代码

-(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 核心概念:将任务添加到队列,指定任务执行的方法

上一篇 下一篇

猜你喜欢

热点阅读