美文网首页
iOS 开发_GCD函数与队列二、面试相关知识

iOS 开发_GCD函数与队列二、面试相关知识

作者: iOS_PM_WEB_尛鹏 | 来源:发表于2018-12-21 17:49 被阅读0次

【作者前言】:13年入圈,分享些本人工作中遇到的点点滴滴那些事儿,17年刚开始写博客,高手勿喷!以分享交流为主,欢迎各路豪杰点评改进!

1.应用场景:

多线程神器---GCD,很多开发的场景中,我们都会使用到。

2.实现目标:

针对面试中可能遇到的问题,进行反向的剖析知识点。

3.代码说明:【比喻~队列与函数存在一种关系:C4-2的组合关系】

1) 知识点预热:首先需要了解同步&异步、串行&并行的关系
  • 同步执行:
    dispatch_sync(),这个函数会把一个block加入到指定的队列中,而且会一直等到执行完blcok,这个函数才返回。因此在block执行完之前,调用dispatch_sync方法的线程是阻塞的。 !>!>!即需要等待执行结果后再执行其他任务

  • 异步执行
    dispatch_async(),这个函数也会把一个block加入到指定的队列中,但是和同步执行不同的是,这个函数把block加入队列后不等block的执行就立刻返回了。 !>!>!即 无需等待执行结果,继续执行其他任务

小结:
dispatch_async() 和 dispatch_sync() 他们的作用是将 任务(block)添加进指定的队列中。并根据是否为sync决定调用该函数的线程是否需要阻塞。
!!!:这里调用该函数的线程并不执行 参数中指定的任务(block块),任务的执行者是GCD分配给任务所在队列的线程。
即 ---> 调用dispatch_sync() 和 dispatch_async() 的线程,并不一定是任务(block块)的真正执行者

  • 串行队列
    如dispatch_get_main_queue() 该队列中所有任务都是串行依次执行,可以保证在执行某个任务时,在它前面进入队列的所有任务肯定执行完了。对于每一个不同的串行队列,系统会为这个队列建立唯一的线程来执行代码

  • 并行队列
    如dispatch_get_global_queue() 该队列中的任务它们的执行结束时间是不确定的,取决于每个任务的耗时。并发队列中的任务:GCD会动态分配多条线程来执行。具体几条线程取决于当前内存使用状况,线程池中线程数等因素

2) 代码实操+详细解读分析
  • 【主队列---串行同步】
/** 主队列---串行同步 --测试
    不会开启线程  等待执行
 */
- (void)mainSyncTest {
    NSLog(@"0");
    
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"1");
    });
    
    NSLog(@"2");
}

/****************控制台输出结果*******************/
 0 --- >崩溃Thread 1: EXC_BAD_INSTRUCTION 造成死锁

/****************结果分析******************/
 打印 0 ---> 正常输出后,
 当前执行这个dispatch_get_main_queue()队列的是主线程。
 执行了dispatch_sync()函数后,将block(打印1) 添加到了main_queue中,
 同时调用dispatch_syn这个函数的线程(也就是主线程)会被阻塞,需要等待
 block(打印1)执行完成,而此时执行主线程队列任务的线程正是主线程,
 此时他处于阻塞状态,所以block(打印1)永远不会被执行,因此主线程一直处于阻塞状态。

 因此这段代码运行后,并非卡在block(打印1)中无法返回,而是根本无法执行到这个block(打印1)!
 导致你等我我等你,形成死锁。无法打印 1 和 2
  • 【主队列---串行异步】
/** 主队列---串行异步 --测试
    不会开启线程, 顺序执行
 */
- (void)mainAysncTest {
    NSLog(@"0");
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"1");
    });
    NSLog(@"2");
}
/****************控制台输出结果******************/
 0 2 1
/****************结果分析******************/
  dispatch_get_main_queue()属于串行队列,顺序执行
  dispatch_async()异步调用,不需要等待直接输出执行结果,
  即 0 ---> 2 ---> 1
  • 【全局队列---并行同步】
/** 全局队列---并行同步 --测试
     不会开辟线程!
 */
- (void)globalSyncTest {
    for (int i = 0; i < 5; i ++) {
        dispatch_sync(dispatch_get_global_queue(0, 0), ^{
            NSLog(@"%d -- %@",i,[NSThread currentThread]);
        });
    }
    for (long i = 0; i < 100000; i ++) {
        //相当于做个一定的延时处理...方便查看效果
    }
    NSLog(@"hello sync Global_Queue");
}

/****************控制台输出结果******************/
0 -- <NSThread: 0x6000003faa40>{number = 1, name = main}
1 -- <NSThread: 0x6000003faa40>{number = 1, name = main}
2 -- <NSThread: 0x6000003faa40>{number = 1, name = main}
3 -- <NSThread: 0x6000003faa40>{number = 1, name = main}
4 -- <NSThread: 0x6000003faa40>{number = 1, name = main}

hello sync Global_Queue
/****************结果分析******************/
dispatch_get_global_queue() 属于并行队列,结果无序
dispatch_sync() 同步调用,需要等待执行结束后在执行其他任务,
即 阻塞当前线程,顺序执行,故并行也无法发挥作用,需要一个等一个依次执行,
所以这里并没有开辟新的线程!
  • 【全局队列---并行异步】
/** 全局队列---并行异步 --测试
 */
- (void)globalAsyncTest {
    for (int i = 0; i < 5; i ++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            NSLog(@"%d -- %@",i,[NSThread currentThread]);
        });
    }
    
    for (long i = 0; i < 100000; i ++) {
        //相当于做个一定的延时处理...方便查看效果
    }
    NSLog(@"hello async Global_Queue");
}

/****************控制台输出结果******************/
 0 -- <NSThread: 0x6000032ae000>{number = 3, name = (null)}
 2 -- <NSThread: 0x6000032ae0c0>{number = 6, name = (null)}
 1 -- <NSThread: 0x6000032adfc0>{number = 4, name = (null)}
 3 -- <NSThread: 0x600003292940>{number = 5, name = (null)}
 4 -- <NSThread: 0x6000032ae000>{number = 3, name = (null)}

 hello async Global_Queue
/****************结果分析******************/
 dispatch_get_global_queue() 属于并行队列,执行结果时序不一定
 dispatch_async()异步调用,不需要等待直接顺序执行,
 所以,线程并非只有一个,开辟了多个线程并行处理任务,输出的结果的顺序也不确定
  • 【通用的串行同步】
/** 串行同步队列 --测试
    不开辟线程   顺序执行
 */
- (void)serialSyncTest {
    dispatch_queue_t serialQueue = dispatch_queue_create("ypSerialQueue", DISPATCH_QUEUE_SERIAL);
    for (int i = 0; i < 5; i ++) {
        dispatch_sync(serialQueue, ^{
            NSLog(@"%d -- %@",i, [NSThread currentThread]);
        });
    }
    
    NSLog(@"hello sync serialQueue");
}
/****************控制台输出结果******************
 0 -- <NSThread: 0x600000365200>{number = 1, name = main}
 1 -- <NSThread: 0x600000365200>{number = 1, name = main}
 2 -- <NSThread: 0x600000365200>{number = 1, name = main}
 3 -- <NSThread: 0x600000365200>{number = 1, name = main}
 4 -- <NSThread: 0x600000365200>{number = 1, name = main}
 
 hello sync serialQueue
 */
/****************结果分析******************
 serialQueue 属于串行队列 不会开辟线程 顺序执行
 dispatch_sync()同步调用,需要等待 顺序执行,
 
 串行队列情况下,只能依次执行,同步调用 等待出结果,故输出如上
 */
  • 【通用的串行异步】
/** 串行异步队列 --测试
    不开辟线程   顺序执行
 */
- (void)serialAsyncTest {
    dispatch_queue_t serialQueue = dispatch_queue_create("ypSerialQueue", DISPATCH_QUEUE_SERIAL);
    for (int i = 0; i < 5; i ++) {
        dispatch_async(serialQueue, ^{
            NSLog(@"%d -- %@",i, [NSThread currentThread]);
        });
    }
    
     NSLog(@"hello serial Queue");
}
/****************控制台输出结果******************
 hello serial Queue
 
 0 -- <NSThread: 0x600003904d40>{number = 3, name = (null)}
 1 -- <NSThread: 0x600003904d40>{number = 3, name = (null)}
 2 -- <NSThread: 0x600003904d40>{number = 3, name = (null)}
 3 -- <NSThread: 0x600003904d40>{number = 3, name = (null)}
 4 -- <NSThread: 0x600003904d40>{number = 3, name = (null)}
 */
/****************结果分析******************
 serialQueue 属于串行队列 不会开辟线程 顺序执行
 dispatch_async()异步调用,不需要等待直接顺序执行,
 
 串行队列情况下,只能依次执行,异步调用直接出结果,故输出如上
 */
  • 【通用的并行同步】
/** 并行同步 ---测试
    不会创建线程  顺序执行
*/
- (void)concurrentSyncTest {
    //创建并发队列
    dispatch_queue_t concurrentQueue = dispatch_queue_create("ypConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 5; i ++) {
        dispatch_sync(concurrentQueue, ^{
            NSLog(@"%d -- %@",i, [NSThread currentThread]);
        });
    }
    
    NSLog(@"hello sync concurrent Queue");
    
}
/****************控制台输出结果******************
 0 -- <NSThread: 0x6000020ee940>{number = 1, name = main}
 1 -- <NSThread: 0x6000020ee940>{number = 1, name = main}
 2 -- <NSThread: 0x6000020ee940>{number = 1, name = main}
 3 -- <NSThread: 0x6000020ee940>{number = 1, name = main}
 4 -- <NSThread: 0x6000020ee940>{number = 1, name = main}
 
 hello sync concurrent Queue
 */

/****************结果分析******************
 concurrentQueue 属于并行队列,执行结果时序不一定
 dispatch_sync()同步调用,需要等待 顺序执行,
 只要同步 就等待执行, 所以没有开辟线程  结果如上
 */
  • 【通用的并行异步】
/** 并行异步:*/
- (void)concurrentAsyncTest {
    //创建并发队列
    dispatch_queue_t concurrentQueue = dispatch_queue_create("ypconcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 5; i ++) {
        dispatch_async(concurrentQueue, ^{
            NSLog(@"%d -- %@",i, [NSThread currentThread]);
        });
    }
    
    for (long i = 0; i < 100000; i ++) {
        //相当于做个一定的延时处理...方便查看效果
    }
    NSLog(@"hello concurrent Queue");
    
}
/****************控制台输出结果******************/
 0 -- <NSThread: 0x600001633600>{number = 3, name = (null)}
 3 -- <NSThread: 0x600001633580>{number = 5, name = (null)}
 2 -- <NSThread: 0x60000160d380>{number = 4, name = (null)}
 1 -- <NSThread: 0x600001633500>{number = 6, name = (null)}
 4 -- <NSThread: 0x600001633580>{number = 5, name = (null)}
 
 hello concurrent Queue
/****************结果分析******************/
 concurrentQueue 属于并行队列,执行结果时序不一定
 dispatch_async() 异步调用,不需要等待直接顺序执行,
 所以,线程并非只有一个,开辟了多个线程并行处理任务,输出的结果的顺序也不确定

相关文章

  • iOS 开发_GCD函数与队列二、面试相关知识

    【作者前言】:13年入圈,分享些本人工作中遇到的点点滴滴那些事儿,17年刚开始写博客,高手勿喷!以分享交流为主,欢...

  • iOS开发多线程之GCD

    iOS开发多线程之GCDiOS开发之GCD同步任务加强iOS开发之GCD串行队列iOS开发之GCD并发队列 GCD...

  • iOS开发之GCD并发队列

    iOS开发多线程之GCDiOS开发之GCD同步任务加强iOS开发之GCD串行队列iOS开发之GCD并发队列 03 ...

  • iOS开发之GCD同步任务加强

    iOS开发多线程之GCDiOS开发之GCD同步任务加强iOS开发之GCD串行队列iOS开发之GCD并发队列 004...

  • iOS开发之GCD串行队列

    iOS开发多线程之GCDiOS开发之GCD同步任务加强iOS开发之GCD串行队列iOS开发之GCD并发队列 实例d...

  • OC多线程学习(二) - GCD

    本文内容: GCD相关概念 有关GCD的几道面试题 源码分析:队列和异步函数 GCD概念 GCD是Grand Ce...

  • GCD的简单使用

    一. GCD基本知识 两个核心概念 队列和任务 同步函数和异步函数 二. GCD基本使用 异步函数+并发队列 : ...

  • Grand Central Dispatch(GCD)编程基础

    本文介绍iOS 多线程中 GCD 的相关知识以及使用方法。通过本文可以了解到: GCD 简介 GCD 任务和队列 ...

  • iOS多线程 - GCD

    本文用来介绍 iOS 多线程中 GCD的相关知识以及使用方法。通过本文,您将了解到:GCD 简介GCD 任务和队列...

  • iOS GCD (二 ) dispatch_group 队列组

    iOS GCD (一) 任务+队列 基础组合iOS GCD (二 ) dispatch_group 队列组iO...

网友评论

      本文标题:iOS 开发_GCD函数与队列二、面试相关知识

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