美文网首页
iOS-GCD的基本使用和死锁问题

iOS-GCD的基本使用和死锁问题

作者: 长衣貌 | 来源:发表于2018-06-30 09:23 被阅读0次

    1./异步函数加并发队列

    /**
     异步函数 + 并发队列 组合
        会开启多条线程,(异步函数具备开线程的能力,但不是每次都必须开新的线程)
        队列中的任务是异步执行的(无序的,一起执行)
     注意:GCD中并发队列开多少条线程是不受控制的,系统会根据CPU使用情况自行决定开多少条线程
     */
    - (void)asyncConcurrent{
        
        /**
         1./创建一个新的队列
         第一个参数:标签(C语言的字符串,不能加 @ 符) 
         第二个参数:创建的是什么类型的队列
            并发:DISPATCH_QUEUE_CONCURRENT
            串行:DISPATCH_QUEUE_SERIAL
         dispatch_queue_t queue = dispatch_queue_create("peiDuo", DISPATCH_QUEUE_CONCURRENT);
         */
        //区别:一个是创建一个新的,一个是程序自带的手动获取的
        /**
         获得一个全局的并发队列 (这个队列本身就存在的)
         第一个参数:优先级 (枚举型 可以直接填 数字)
            DISPATCH_QUEUE_PRIORITY_HIGH 2 : 最高级
            DISPATCH_QUEUE_PRIORITY_DEFAULT 0 : 默认的
            DISPATCH_QUEUE_PRIORITY_LOW (-2):低级的
            DISPATCH_QUEUE_PRIORITY_BACKGROUND:后台优先级(最低的)
         第二个参数:留给未来使用的(xcode更新后有可能使用上) 默认填 0
         */
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
        
        /**
         2./封装任务 通过block块来封装任务
         第一个参数:添加到哪一个队列
         第二个参数:要执行什么任务
         */
        dispatch_async(queue, ^{
            NSLog(@"任务1 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务2 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务3 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务4 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务5 当前线程--%@",[NSThread currentThread]);
        });
        
    }
    

    打印结果:


    屏幕快照 2018-06-30 09.26.22.png

    2./异步函数 + 串行队列 组合

    /**
     异步函数 + 串行队列 组合
        会开线程 (只开一条线程)
        队列中的任务是串行执行的(串行是一个执行完成后再执行下一个)
     */
    - (void)asyncSerial{
        
        /**
        1./创建队列
        第一个参数:标签(C语言的字符串,不能加 @ 符)
        第二个参数:创建的是什么类型的队列
        并发:DISPATCH_QUEUE_CONCURRENT
        串行:DISPATCH_QUEUE_SERIAL
        */
        dispatch_queue_t queue = dispatch_queue_create("peiDuo", DISPATCH_QUEUE_SERIAL);
        
        /**
         2./封装任务 通过block块来封装任务
         第一个参数:添加到哪一个队列
         第二个参数:要执行什么任务
         */
        dispatch_async(queue, ^{
            NSLog(@"任务1 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务2 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务3 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务4 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务5 当前线程--%@",[NSThread currentThread]);
        });
    }
    

    打印结果:


    屏幕快照 2018-06-30 09.28.56.png

    3./同步函数 + 并发队列 组合

    /**
     同步函数 + 并发队列 组合
        同步函数不会开线程
        不管是什么队列都会在主线程执行
     */
    - (void)syncConcurrent{
        
        /**
         1./创建队列
         第一个参数:标签(C语言的字符串,不能加 @ 符)
         第二个参数:创建的是什么类型的队列
         并发:DISPATCH_QUEUE_CONCURRENT
         串行:DISPATCH_QUEUE_SERIAL
         */
        dispatch_queue_t queue = dispatch_queue_create("peiDuo", DISPATCH_QUEUE_CONCURRENT);
        
        /**
         2./封装任务 通过block块来封装任务
         第一个参数:添加到哪一个队列
         第二个参数:要执行什么任务
         */
        dispatch_sync(queue, ^{
            NSLog(@"任务1 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"任务2 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"任务3 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"任务4 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"任务5 当前线程--%@",[NSThread currentThread]);
        });
        
    }
    

    打印结果:


    屏幕快照 2018-06-30 09.30.28.png

    4./同步函数 + 串行队列

    /**
     同步函数 + 串行队列
        同步函数不会开线程
        不管是什么队列都会在主线程执行
     */
    - (void)syncSerial{
        
        /**
         1./创建队列
         第一个参数:标签(C语言的字符串,不能加 @ 符)
         第二个参数:创建的是什么类型的队列
         并发:DISPATCH_QUEUE_CONCURRENT
         串行:DISPATCH_QUEUE_SERIAL
         */
        dispatch_queue_t queue = dispatch_queue_create("peiDuo", DISPATCH_QUEUE_SERIAL);
        
        /**
         2./封装任务 通过block块来封装任务
         第一个参数:添加到哪一个队列
         第二个参数:要执行什么任务
         */
        dispatch_sync(queue, ^{
            NSLog(@"任务1 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"任务2 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"任务3 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"任务4 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"任务5 当前线程--%@",[NSThread currentThread]);
        });
    }
    

    打印结果:


    屏幕快照 2018-06-30 09.31.47.png

    5./异步函数 + 主队列

    /**
     异步函数 + 主队列
        不会开启子线程,说有放在主队列中的任务都必须在主线程中执行
     */
    - (void)asyncMain{
        
        //获得主队列
        dispatch_queue_t queue = dispatch_get_main_queue();
        
        /**
         2./封装任务 通过block块来封装任务
         第一个参数:添加到哪一个队列
         第二个参数:要执行什么任务
         */
        dispatch_async(queue, ^{
            NSLog(@"任务1 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务2 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务3 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务4 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务5 当前线程--%@",[NSThread currentThread]);
        });
    }
    

    打印结果:


    屏幕快照 2018-06-30 09.32.35.png

    6./同步函数 + 主队列

    /**
     同步函数 + 主队列
     同步函数加主队列会造成死锁
     同步函数的特点:立刻马上执行,一个任务没有执行完其他的任务不能执行,
     主队列特点:如果主队列发现当前主线程内有任务在执行那么主队列会暂停调用队列中的任务,直到主线程空闲
     但是在子线程内调用同步函数➕主队列不会造成死锁
     */
    - (void)syncMain{
        
        //获得主队列
        dispatch_queue_t queue = dispatch_get_main_queue();
        
        NSLog(@"start");
        
        /**
         2./封装任务 通过block块来封装任务
         第一个参数:添加到哪一个队列
         第二个参数:block块要执行什么任务
         */
        dispatch_sync(queue, ^{
            NSLog(@"任务1 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"任务2 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"任务3 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"任务4 当前线程--%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"任务5 当前线程--%@",[NSThread currentThread]);
        });
        
        NSLog(@"end");
    }
    

    打印结果:


    屏幕快照 2018-06-30 09.33.14.png

    程序崩溃了 ,

    原因:
    同步函数加主队列会造成死锁
    同步函数的特点:立刻马上执行,一个任务没有执行完其他的任务不能执行,
    主队列特点:如果主队列发现当前主线程内有任务在执行那么主队列会暂停调用队列中的任务,直到主线程空闲
    双方会互相等待.

    但是在子线程内调用同步函数➕主队列不会造成死锁

    这个一定要清楚,面试的时候也会问到死锁问题.

    相关文章

      网友评论

          本文标题:iOS-GCD的基本使用和死锁问题

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