美文网首页
GCD编程探索(一)

GCD编程探索(一)

作者: guchengfeng | 来源:发表于2018-08-17 17:20 被阅读0次
     苹果官方给出的解释:GCD是异步执行任务的技术之一。一般将应用程序中记述的线程管理代码在系统集中实现,开发者只需要定义想执行的任务并追加到适当的Dispatch
    Queue中,GCD就可以生成必要的线程并计划执行任务。
    

    GCD的概念

    GCD 是Grand Central Dispatch的缩写,是苹果对多核硬件上执行并发代码的一种支持。GCD有一下特点
    • GCD通过把计算密集型任务放于后台运行,以此提高APP的响应速度(多线程)
    • GCD提供了更简单的并发模型,它优于线程锁,并且帮助你避免并发bug。(安全)
    • GCD基于底层、高性能的优化常规类型的代码,例如单例。(高效)
    • GCD代码简洁,使用方便(简洁)

    GCD的术语

    GCD的概念主要包括串行,并行,同步,异步,危险区,竞态条件,死锁,线程安全,环境切换.
    概念 作用 通俗解释
    串行 事件按顺序执行 A - B - C
    并行 事件可以同时发生 A/B/C
    同步 不开启新的线程 只有代码块完成了才可以继续执行
    异步 开启新的线程 可以继续执行
    危险区 共享代码区 临界区
    竞态条件 共享代码区别访问 数据会发生破坏
    死锁 任务和线程的相互等待 循环等待
    线程安全 数据不可以被多个线程访问 NSDictionary
    环境切换 线程切换执行状态恢复和处理 多任务App

    GCD的实验

    实验1 串行 + 同步

        NSLog(@"线程:%@开始看延禧攻略",[NSThread currentThread]);
        //串行
        dispatch_queue_t queue = dispatch_queue_create("SERIAL_1", DISPATCH_QUEUE_SERIAL);
        //同步
        dispatch_sync(queue, ^{
            NSLog(@"线程:%@正在看延禧攻略",[NSThread currentThread]);
        });
        NSLog(@"线程:%@看完了延禧攻略",[NSThread currentThread]);
    
        2018-08-17 15:41:15.051488+0800 TestGCD[8476:227832] 线程:<NSThread: 0x604000070b80>{number = 1, name = main}开始看延禧攻略
        2018-08-17 15:41:15.051628+0800 TestGCD[8476:227832] 线程:<NSThread: 0x604000070b80>{number = 1, name = main}正在看延禧攻略
        2018-08-17 15:41:15.051735+0800 TestGCD[8476:227832] 线程:<NSThread: 0x604000070b80>{number = 1, name = main}看完了延禧攻略
    
    
    

    专家分析:

    • 先执行 ==开始看延禧攻略==
    • 判断为同步执行,执行 ==正在看延禧攻略==
    • 执行==看完了延禧攻略==

    <html>
    <p style="color:red;">注意:虽然有两个线程,但任务要按顺序取出来,所以也只能执行一个任务</p>
    </html>


    实验2 串行 + 异步

        NSLog(@"线程:%@开始看延禧攻略",[NSThread currentThread]);
        //串行
        dispatch_queue_t queue = dispatch_queue_create("SERIAL_1", DISPATCH_QUEUE_SERIAL);
        //异步
        dispatch_async(queue, ^{
            NSLog(@"线程:%@正在看延禧攻略",[NSThread currentThread]);
        });
        NSLog(@"线程:%@看完了延禧攻略",[NSThread currentThread]);
    
        2018-08-17 15:52:04.038083+0800 TestGCD[8799:238132] 线程:<NSThread: 0x60000007c800>{number = 1, name = main}开始看延禧攻略
        2018-08-17 15:52:04.038267+0800 TestGCD[8799:238132] 线程:<NSThread: 0x60000007c800>{number = 1, name = main}看完了延禧攻略
        2018-08-17 15:52:04.038299+0800 TestGCD[8799:238199] 线程:<NSThread: 0x60c000260340>{number = 3, name = (null)}正在看延禧攻略
    
    

    专家分析:

    • 先执行 ==开始看延禧攻略==
    • 判断为串行队列,将 ==正在看延禧攻略== 追加到串行队列后面,这个时候顺序为 ==开始看延禧攻略== ==看完了延禧攻略== ==正在看延禧攻略== ;判断为异步执行,新开启一个线程)
    • 从串行队列取出任务依次执行

    实验3 并行 + 同步

        NSLog(@"线程:%@开始看延禧攻略",[NSThread currentThread]);
        //并行
        dispatch_queue_t queue = dispatch_queue_create("SERIAL_1", DISPATCH_QUEUE_CONCURRENT);
        //异步
        dispatch_sync(queue, ^{
            NSLog(@"线程:%@正在看延禧攻略",[NSThread currentThread]);
        });
        NSLog(@"线程:%@看完了延禧攻略",[NSThread currentThread]);
    
        
        2018-08-17 16:19:18.103827+0800 TestGCD[9522:258973] 线程:<NSThread: 0x600000261b40>{number = 1, name = main}开始看延禧攻略
        2018-08-17 16:19:18.104044+0800 TestGCD[9522:258973] 线程:<NSThread: 0x600000261b40>{number = 1, name = main}正在看延禧攻略
        2018-08-17 16:19:18.104147+0800 TestGCD[9522:258973] 线程:<NSThread: 0x600000261b40>{number = 1, name = main}看完了延禧攻略
        
        
    

    专家分析:

    • 先执行 ==开始看延禧攻略==
    • 判断为并行队列,将 ==正在看延禧攻略== 追加到一个新的队列里面;判断为同步执行,所以只有一个线程
    • 只有一个线程,先从队列1取出==开始看延禧攻略==,再从队列2取出 ==正在看延禧攻略==,再从队列1取出 ==看完了延禧攻略==

    <html>
    <p style="color:red;">注意:虽然有两个任务队列,但只有一个线程,所以也只能执行一个任务</p>
    </html>

    实验4 并行 + 异步

        NSLog(@"线程:%@开始看延禧攻略",[NSThread currentThread]);
        //并行
        dispatch_queue_t queue = dispatch_queue_create("SERIAL_1", DISPATCH_QUEUE_CONCURRENT);
        //异步
        dispatch_async(queue, ^{
            NSLog(@"线程:%@正在看延禧攻略",[NSThread currentThread]);
        });
        NSLog(@"线程:%@看完了延禧攻略",[NSThread currentThread]);
        
        2018-08-17 16:38:38.335505+0800 TestGCD[10077:274421] 线程:<NSThread: 0x60c000261e80>{number = 1, name = main}开始看延禧攻略
        2018-08-17 16:38:38.335701+0800 TestGCD[10077:274421] 线程:<NSThread: 0x60c000261e80>{number = 1, name = main}看完了延禧攻略
        2018-08-17 16:38:38.335727+0800 TestGCD[10077:274480] 线程:<NSThread: 0x60400026a780>{number = 3, name = (null)}正在看延禧攻略
        
    

    专家分析:

    • 先执行 ==开始看延禧攻略==
    • 判断为并行队列,将 ==正在看延禧攻略== 追加到一个新的队列里面;判断为同步执行,有两个线程
    • 两个线程分别从两个队列取出任务去执行

    实验5 主队列 + 同步

        NSLog(@"线程:%@开始看延禧攻略",[NSThread currentThread]);
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"线程:%@正在看延禧攻略",[NSThread currentThread]);
        });
        NSLog(@"线程:%@看完了延禧攻略",[NSThread currentThread]);
        
        2018-08-17 16:49:11.267733+0800 TestGCD[10403:283929] 线程:<NSThread: 0x608000069840>{number = 1, name = main}开始看延禧攻略
        
        崩溃
        
    

    实验6 主队列 + 异步

        NSLog(@"线程:%@开始看延禧攻略",[NSThread currentThread]);
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"线程:%@正在看延禧攻略",[NSThread currentThread]);
        });
        NSLog(@"线程:%@看完了延禧攻略",[NSThread currentThread]);
        
        2018-08-17 16:59:03.154983+0800 TestGCD[10697:291985] 线程:<NSThread: 0x60c000062fc0>{number = 1, name = main}开始看延禧攻略
        2018-08-17 16:59:03.155130+0800 TestGCD[10697:291985] 线程:<NSThread: 0x60c000062fc0>{number = 1, name = main}看完了延禧攻略
        2018-08-17 16:59:03.158271+0800 TestGCD[10697:291985] 线程:<NSThread: 0x60c000062fc0>{number = 1, name = main}正在看延禧攻略
    
    总结:队列分串行和并行,每个队列相当于一个线性的任务表单。执行方式分同步和异步,相当于执行的物理单元。
    
    下面以指压板(奔跑吧)为例子
    
    同步 + 串行:
    
    假设奔跑吧里面:anglebaby拿到指压板任务清单,将任务按顺序去完成,先跳绳-赛跑-跨栏-仰卧爬行
    
    同步 + 并行:
    
    假设奔跑吧里面:anglebaby拿到指压板任务清单1和清单2,先完成清单1 跳绳-赛跑,再完成清单2 ,跨栏-仰卧爬行
    
    异步 + 串行:
    
    假设奔跑吧里面:anglebaby和邓超上场,只有anglebagy拿到指压板任务清单,,先跳绳-赛跑-跨栏-仰卧爬行,邓超作为新的线程没有任务可以完成
    
    异步 + 并行:anglebaby和邓超上场,只有anglebagy拿到指压板任务清单1,跳绳-赛跑,邓超作为新的线程拿到清单2,完成跨栏,仰卧爬行
    

    相关文章

      网友评论

          本文标题:GCD编程探索(一)

          本文链接:https://www.haomeiwen.com/subject/xyetiftx.html