• iOS多线程GCD的简单使用


    在iOS开发中,苹果提供了三种多线程技术,分别是:

    (1)NSThread

    (2)NSOperation

    (3)GCD

    简单介绍一下GCD的使用。

    GCD全称 Grand Central Dispatch,可以称之为大中央调度。实际上GCD是管理着一个线程池,如何创建线程,如何回收线程,以及分配多少个线程,这些都是GCD来控制的。在开发中,程序员是不用操作线程的相关事情,程序员只需要把应该做的操作放到相应的队列里面即可。

    一:自定义队列

    GCD中有多种队列,其中自定义的队列有两种:串行队列和并行队列

    1:串行队列:队列中的任务只会顺序执行,且一次只能够执行一个任务。也就是说,执行完一个任务后,才会执行下一个任务

    2:并行队列:可以一次执行多个任务。比如说并行队列中有10个任务,可以一次执行3个任务,这三个任务哪个先执行完了,再接着执行剩下的任务。

    注意:无论是串行队列还是并行队列,他们都是FIFO(先进先出)的。也就是说,无论是哪种队列,任务进队列的时间越早,其执行的时间就越早(只不过某些情况下任务执行的结束时间是不确定的)。

    GCD中有两种操作,分别是同步操作和异步操作

    1:同步操作:不会新开线程

    2:异步操作:会开启新的线程

    两种操作和两种队列,组合为4种情况,实际上,在开发中,有些组合基本上是不会用到的。下面用程序描述一下四种组合。

    组合一:串行队列+同步操作(不会新建线程,而且任务是一个一个的执行,因此实际上就是顺序执行),代码如下:

    - (void)gcdDemo1
    {
        //串行队列+同步操作
        dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_SERIAL);
        for(int i = 0; i < 10; ++i){
            dispatch_sync(queue, ^{
                NSLog(@"%@ %d",[NSThread currentThread],i);
            });
        }
    }
    

    执行结果:

    number = 1,说明是主线程,没有新开线程。

    组合二:串行队列+异步操作(因为任务要一个一个的执行,但是因为是异步操作,所以会开启一个新的线程,所有的任务都在新的线程上执行),代码如下:

    - (void)gcdDemo1
    {
        dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_SERIAL);
        //串行队列+异步操作
        for (int i = 0; i < 10; ++i){
            dispatch_async(queue, ^{
                NSLog(@"%@ %d",[NSThread currentThread],i);
            });
        }
    }

    执行结果:

    number = 2,说明开启了一个新的子线程,但仍然是顺序执行。

    组合三:并行队列+同步操作(因为同步操作不会开启新的线程,因此,即使并行队列可以一次开始多个任务,但实际上仍旧是每个任务都在主线程上执行,且按顺序执行)。代码如下:

    - (void)gcdDemo2
    {
        dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_CONCURRENT);
        //并行队列+同步任务
        for(int i = 0; i < 10; ++i){
            dispatch_sync(queue, ^{
                NSLog(@"%@ %d",[NSThread currentThread],i);
            });
        }
    }

    执行结果:

    没有开启新的线程,且按顺序执行。

    组合四:并行队列+异步操作(并行队列会一次开始多个任务,且异步操作可以开启新的线程,因此同一时刻可能会同时执行多个任务,开启多个线程,且每个任务的结束时间是不确定的)。代码如下:

    - (void)gcdDemo2
    {
        dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_CONCURRENT);
        //并行队列+异步任务
        for(int i = 0; i < 10; ++i){
            dispatch_async(queue, ^{
                NSLog(@"%@ %d",[NSThread currentThread],i);
            });
        }
    }

    执行结果:

    可以看到,开启了多个线程,且任务不是按顺序执行完的。

    二:全局队列

    为了方便开发,苹果还提供了有全局队列,全局队列实际上是并行队列,因此,全局队列的执行结果和并行队列的执行结果是一致的。代码如下:

    全局队列+同步任务:

    - (void)gcdDemo3
    {
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        //全局队列+同步任务
        for (int i = 0; i < 10; ++i){
            //同步任务
            dispatch_sync(queue, ^{
                NSLog(@"%@ %d",[NSThread currentThread],i);
            });
        }
    }

    执行结果:

    全局队列+异步任务:

    - (void)gcdDemo3
    {
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        //全局队列+异步任务
        for(int i = 0; i < 10; ++i){
            dispatch_async(queue, ^{
                NSLog(@"%@ %d",[NSThread currentThread],i);
            });
        }
    }

    执行结果:

    三:主队列

    苹果还提供了一种队列是主队列,主队列是串行队列,但是和串行队列又有差异。主队列上的任务都应该在主线程上顺序执行,没有异步的概念。也就是说,即使是异步任务在主队列上执行,也不会开启新的线程。

    主队列+异步任务:

    - (void)gcdDemo4
    {
        dispatch_queue_t queue = dispatch_get_main_queue();
        //主队列+异步任务
        for(int i = 0; i < 10; ++i){
            dispatch_async(queue,^{
                NSLog(@"%@ %d",[NSThread currentThread],i);
            });
        }
    }

    执行结果:

    可以看到,没有开启新的线程,且是顺序执行。

    主队列+同步任务(会阻塞线程),代码如下:

    - (void)gcdDemo4
    {
        dispatch_queue_t queue = dispatch_get_main_queue();
        //主队列+同步任务,会阻塞
        for(int i = 0; i < 10; ++i){
            dispatch_sync(queue, ^{
                NSLog(@"%@ %d",[NSThread currentThread],i);
            });
        }
    }

    阻塞原因:

    主队列中本身是有一个任务A的(主任务),且该任务A还没有执行完。在执行任务A的过程中,又插入了新的同步任务B。我们知道,串行队列中,必须先执行完一个任务后,才能继续执行另一个任务。此时的情况时:

    若想继续执行任务A,需要先把任务B执行完,若想继续执行任务B,需要先把任务A执行完,因此造成了阻塞。

    在开发中,应该避免这种阻塞的情况。

  • 相关阅读:
    tree
    mkdir
    touch
    rename
    dirname
    vue之导入Bootstrap以及jQuery的两种方式
    Vue组件系统
    报错:ERROR! The server quit without updating PID file (/usr/local/var/mysql/chenyuntekiMacBook-Air.local.pid).
    Linux命令
    Vue知识点小总结1
  • 原文地址:https://www.cnblogs.com/acBool/p/5137062.html
Copyright © 2020-2023  润新知