iOS归纳

GCD函数与队列&其他详尽总结

2020-11-05  本文已影响0人  猿人

简介

概念

1.全称是 Grand Central Dispatch,纯 C 语言,提供了非常多强大的函数

1.Grand Central Dispatch(GCD) 是 Apple 开发的一个多核编程的较新的解决方法。它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并发任务。在 Mac OS X 10.6 雪豹中首次推出,也可在 iOS 4 及以上版本使用。
2.官方文档介绍:https://developer.apple.com/documentation/dispatch

2.将任务添加到队列,并且指定执行任务的函数

优势

1.GCD是apple为多核的并行运算提出的解决方案。
2.GCD能较好的利用CPU内核资源。
3.GCD不需要开发者去管理线程的生命周期。
4.使用简便,开发者只需要告诉GCD执行什么任务,并不需要编写任何线程管理代码。

任务和队列

任务

就是需要执行的操作,是 GCD 中放在 block 中在线程中执行的那段代码
先看一下下面的代码我们将其进行拆分,还原最基础的写法。

- (void)syncTest{
    // 把任务添加到队列 --> 函数
    // 任务 _t ref c对象
    dispatch_block_t block = ^{
        NSLog(@"hello GCD");
    };
    //串行队列
    dispatch_queue_t queue = dispatch_queue_create("com.lg.cn", NULL);
    // 函数
    dispatch_async(queue, block);
    
    // 函数 队列
    // 函数队列
    // block () - GCD 下层封装
    
}

再去想上面的总结【将任务添加到队列,并且指定执行任务的函数】然后我们就能明白 所谓的任务就是就是 block里的执行。
分析:

函数

执行任务的函数,将任务放入队列中,下层进行任务与队列的关系处理。

  1. 异步函数
    dispatch_async(queue, block);
  1. 同步函数
    dispatch_sync(queue, block);
队列

下面所示就是如何创建队列

  1. 串行队列
dispatch_queue_t queue = dispatch_queue_create("com.lg.cn", NULL);
  1. 并发队列
dispatch_queue_t queue = dispatch_queue_create("com.lg.cn", DISPATCH_QUEUE_CONCURRENT);

除了上面的两种队列 还有下面两种较特殊的队列写法

  1. 主队列
 dispatch_queue_t mainQueue = dispatch_get_main_queue();
  1. 全局队列
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0)
截屏2020-11-05 下午6.03.34.png

注意:
1.任务资源有大有小(函数内部复杂度不同,执行耗时也不同)
2.队列不可执行任务,只是一个FIFO(先进先出)的存储容器,任务是由cpu调度的线程来执行
3.出队列不是立马执行,而是等待cpu调度到可执行的线程中

函数和队列组合

1、同步函数串行队列

- (void)serialSyncTest{
    //1:创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("Cooci", DISPATCH_QUEUE_SERIAL);
    for (int i = 0; i<13; i++) {
        dispatch_sync(queue, ^{
            NSLog(@"%d-%@",i,[NSThread currentThread]);
        });
    }
 }

运行:

函数与队列[7013:320867] 0-<NSThread: 0x6000020a8300>{number = 1, name = main}
函数与队列[7013:320867] 1-<NSThread: 0x6000020a8300>{number = 1, name = main}
函数与队列[7013:320867] 2-<NSThread: 0x6000020a8300>{number = 1, name = main}
函数与队列[7013:320867] 3-<NSThread: 0x6000020a8300>{number = 1, name = main}
函数与队列[7013:320867] 4-<NSThread: 0x6000020a8300>{number = 1, name = main}
函数与队列[7013:320867] 5-<NSThread: 0x6000020a8300>{number = 1, name = main}
函数与队列[7013:320867] 6-<NSThread: 0x6000020a8300>{number = 1, name = main}
函数与队列[7013:320867] 7-<NSThread: 0x6000020a8300>{number = 1, name = main}
函数与队列[7013:320867] 8-<NSThread: 0x6000020a8300>{number = 1, name = main}
函数与队列[7013:320867] 9-<NSThread: 0x6000020a8300>{number = 1, name = main}
函数与队列[7013:320867] 10-<NSThread: 0x6000020a8300>{number = 1, name = main}
函数与队列[7013:320867] 11-<NSThread: 0x6000020a8300>{number = 1, name = main}
函数与队列[7013:320867] 12-<NSThread: 0x6000020a8300>{number = 1, name = main}

2、同步函数并发队列

///同步 +并发队列
-(void)concurrectSyncTest{
    //创建并发队列
    dispatch_queue_t queue = dispatch_queue_create("com.hh.jj", DISPATCH_QUEUE_CONCURRENT);
    for(int i = 0;i<10; i++){
       ///同步函数
        dispatch_sync(queue, ^{
            NSLog(@"%d-%@",i,[NSThread currentThread]);
        });
    }
    NSLog(@"hello queue");
 }

运行

函数与队列[7422:360463] 0-<NSThread: 0x600002838840>{number = 1, name = main}
函数与队列[7422:360463] 1-<NSThread: 0x600002838840>{number = 1, name = main}
函数与队列[7422:360463] 2-<NSThread: 0x600002838840>{number = 1, name = main}
函数与队列[7422:360463] 3-<NSThread: 0x600002838840>{number = 1, name = main}
函数与队列[7422:360463] 4-<NSThread: 0x600002838840>{number = 1, name = main}
函数与队列[7422:360463] 5-<NSThread: 0x600002838840>{number = 1, name = main}
函数与队列[7422:360463] 6-<NSThread: 0x600002838840>{number = 1, name = main}
函数与队列[7422:360463] 7-<NSThread: 0x600002838840>{number = 1, name = main}
函数与队列[7422:360463] 8-<NSThread: 0x600002838840>{number = 1, name = main}
函数与队列[7422:360463] 9-<NSThread: 0x600002838840>{number = 1, name = main}
函数与队列[7422:360463] hello queue

3、异步函数串行队列

///串行队列 + 异步函数
-(void)serialAsyncTest{
    //1.创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("com.hh.jj", DISPATCH_QUEUE_SERIAL);
    for (int i = 0; i<10; i++) {
        dispatch_async(queue, ^{
            NSLog(@"%d-%@",i,[NSThread currentThread]);

        });
    }
    NSLog(@"hello queue");
 }

运行

函数与队列[7529:367173] hello queue
函数与队列[7529:367346] 0-<NSThread: 0x600001136440>{number = 6, name = (null)}
函数与队列[7529:367346] 1-<NSThread: 0x600001136440>{number = 6, name = (null)}
函数与队列[7529:367346] 2-<NSThread: 0x600001136440>{number = 6, name = (null)}
函数与队列[7529:367346] 3-<NSThread: 0x600001136440>{number = 6, name = (null)}
函数与队列[7529:367346] 4-<NSThread: 0x600001136440>{number = 6, name = (null)}
函数与队列[7529:367346] 5-<NSThread: 0x600001136440>{number = 6, name = (null)}
函数与队列[7529:367346] 6-<NSThread: 0x600001136440>{number = 6, name = (null)}
函数与队列[7529:367346] 7-<NSThread: 0x600001136440>{number = 6, name = (null)}
函数与队列[7529:367346] 8-<NSThread: 0x600001136440>{number = 6, name = (null)}
函数与队列[7529:367346] 9-<NSThread: 0x600001136440>{number = 6, name = (null)}

4、异步函数并发队列

///并发队列 + 异步函数
-(void)concurrentAsyncTest{
    ///1.创建并发队列
    dispatch_queue_t queue = dispatch_queue_create("com.hh.jj", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i<10 ; i++) {
        dispatch_async(queue, ^{
            NSLog(@"%d-%@",i,[NSThread currentThread]);

        });
    }
    NSLog(@"hello queue");
}

运行

函数与队列[7666:379427] hello queue
函数与队列[7666:379501] 0-<NSThread: 0x6000008d1980>{number = 6, name = (null)}
函数与队列[7666:379506] 2-<NSThread: 0x6000008d5a80>{number = 3, name = (null)}
函数与队列[7666:379502] 3-<NSThread: 0x6000008d89c0>{number = 7, name = (null)}
函数与队列[7666:379503] 1-<NSThread: 0x6000008d5b40>{number = 4, name = (null)}
函数与队列[7666:379501] 4-<NSThread: 0x6000008d1980>{number = 6, name = (null)}
函数与队列[7666:379506] 5-<NSThread: 0x6000008d5a80>{number = 3, name = (null)}
函数与队列[7666:379505] 6-<NSThread: 0x6000008ae480>{number = 8, name = (null)}
函数与队列[7666:379502] 7-<NSThread: 0x6000008d89c0>{number = 7, name = (null)}
函数与队列[7666:379501] 8-<NSThread: 0x6000008d1980>{number = 6, name = (null)}
函数与队列[7666:379503] 9-<NSThread: 0x6000008d5b40>{number = 4, name = (null)}

5、同步函数主队列


2251862-60f29c3661eccc63.png

6、异步函数主队列。

/**
 主队列异步
 不会开线程,并且 永远优先执行 异步函数任务 之外的 任务无论任务多复杂。在顺序执行异步函数任务
 */
- (void)mainAsyncTest{
    dispatch_queue_t queue =   dispatch_get_main_queue();
    for (int i = 0; i<10; i++) {
         dispatch_async(queue, ^{
             
             NSLog(@"%d-%@",i,[NSThread currentThread]);
         });
     }
  
    NSLog(@"hello queue");
    NSLog(@"hello queue");
    NSLog(@"hello queue");
   
}

运行

函数与队列[8762:452443] hello queue
函数与队列[8762:452443] hello queue
函数与队列[8762:452443] hello queue
函数与队列[8762:452443] 0-<NSThread: 0x600002db0380>{number = 1, name = main}
函数与队列[8762:452443] 1-<NSThread: 0x600002db0380>{number = 1, name = main}
函数与队列[8762:452443] 2-<NSThread: 0x600002db0380>{number = 1, name = main}
函数与队列[8762:452443] 3-<NSThread: 0x600002db0380>{number = 1, name = main}
函数与队列[8762:452443] 4-<NSThread: 0x600002db0380>{number = 1, name = main}
函数与队列[8762:452443] 5-<NSThread: 0x600002db0380>{number = 1, name = main}
函数与队列[8762:452443] 6-<NSThread: 0x600002db0380>{number = 1, name = main}
函数与队列[8762:452443] 7-<NSThread: 0x600002db0380>{number = 1, name = main}
函数与队列[8762:452443] 8-<NSThread: 0x600002db0380>{number = 1, name = main}
函数与队列[8762:452443] 9-<NSThread: 0x600002db0380>{number = 1, name = main}

常见相关面试题

面试题 -1

- (void)textDemo{
    dispatch_queue_t queue = dispatch_queue_create("cooci", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"1");
    // 耗时
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_async(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
     NSLog(@"5");
 }

分析

面试题 -2

- (void)wbinterDemo{//
    dispatch_queue_t queue = dispatch_queue_create("com.lg.cooci.cn", DISPATCH_QUEUE_CONCURRENT);
    // 1 2 3
    //  0 (7 8 9)
    dispatch_async(queue, ^{ // 耗时
        NSLog(@"1");
    });
    dispatch_async(queue, ^{
        NSLog(@"2");
    });
    
    // 堵塞哪一行
    dispatch_sync(queue, ^{
        NSLog(@"3");
    });
    
    NSLog(@"0");

    dispatch_async(queue, ^{
        NSLog(@"7");
    });
    dispatch_async(queue, ^{
        NSLog(@"8");
    });
    dispatch_async(queue, ^{
        NSLog(@"9");
    });

分析:首先是一个并发队列。并发队列可以同一时刻执行多个任务。就是比较宽。的数据结构。然后12任务的执行函数为异步。异步函数+并发队列可开启多条线程 。3任务的执行函数为同步,同步函数+并发队列不会开启新的线程。会阻塞当前线程,直到它自己的任务完成。 0在当前线程上。所以 3和0处在一条线程上,并且3一定在0 的前边。7 8 9 任务依旧是由异步函数执行的。所以会开启多线程。这里请注意并不是每写一个异步函数 +添加到队列 就会向对应得开启一条新的线程。下面画图表示

面试-2.jpg
扩展 线程的5种状态

1、新生状态: 当我们用NSTherad构造方法创建一个新线程时。如

    NSThread * th = [[NSThread alloc]initWithTarget:self selector:@selector(wbinterDemo) object:nil];

2、就绪状态: 新建线程对象后,调用该线程的 start()方法就可以启动线程。

 [th start];

3、运行状态: 当就绪状态的线程被调用并获得处理器资源时,线程就进入了运行状态。

4、阻塞状态:一个正在执行的线程在某些特殊情况下,如被人为挂起或需要执行耗时的输入输出操作时,将让出 CPU 并暂时中止自己的执行,进入堵塞状态。

5、死亡状态: 线程主动取消,自然死亡。线程即处于死亡状态。处于死亡状态的线程不具有继续运行的能力。(苹果主线程自动加入runloop,子线程需要手动加入)

上一篇 下一篇

猜你喜欢

热点阅读