GCD串行并发队列

作者: iOSTbag | 来源:发表于2016-04-19 16:36 被阅读1840次

学习完本篇,您会对以下知识点更加理解:

  • 队列
  • 串行队列
  • 并发队列
  • GCD全局队列
  • GCD主队列
  • 创建串行队列
  • 创建并发队列

Paste_Image.png

队列

不管是什么队列,一定是FIFO队列,即先进先出。
所以,请大家记住了:不管是串行队列(SerialQueue)还是并发队列(ConcurrencyQueue),都是FIFO队列。也就意味着,任务一定是一个一个地,按照先进先出的顺序来执行。
串行队列:在创建队列时,传参数DISPATCH_QUEUE_SERIAL表示创建串行队列。任务会一个一个地执行,只有前一个任务执行完成,才会继续执行下一个任务。串行执行并不是同步执行的意思,一定要注意区分
并发队列:在创建队列时,传参数DISPATCH_QUEUE_CONCURRENT表示创建并发队列。并发队列会尽可能多地创建线程去执行任务。并发队列中的任务会按入队的顺序执行任务,但是哪个任务先完成是不确定的。

队列类型

苹果提供了以下队列:

全局队列:苹果预定义的全局并发队列,只能通过苹果提供的API来获取,可以设置优先级。
主队列:在应用启动的时候,就会自动创建与主线程关联的串行队列,我们也可能获取,不能手动创建。
手动创建串行队列
手动创建并发队列

全局队列

全局队列的第二个参数用于设置优先级,只有下面四个选项:
DISPATCH_QUEUE_PRIORITY_HIGH 2
DISPATCH_QUEUE_PRIORITY_DEFAULT 0
DISPATCH_QUEUE_PRIORITY_LOW (-2)
DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN"
我们通常使用默认选项,所以很多时候看到的都是传0。下面我们来看看创建四个任务放到并发队列中异步地执行:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"1");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 睡眠2秒
sleep(2);
NSLog(@"2");
});

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   // 睡眠3秒
   sleep(1);
  NSLog(@"3");
  });

打印结果如下:


Paste_Image.png

三个任务分别在三个线程中进行才有三个线程号。
上面的代码中,我们在并发队列中添加了三个任务,其中任务1是直接执行,任务2是在异步执行过程中被睡眠2秒,任务3在异步执行过程中被睡眠1秒,结果任务3先于任务2执行完成。说明并发执行任务并不需要等待其他任务先执行完。对于这三个任务,是互不干扰的!
当然,全局队列可以指定任务执行的优先级的,比如下面:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSLog(@"4");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSLog(@"3");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"2");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSLog(@"1");
});

Paste_Image.png

优先级由高到低顺序运行 任务一优先级最高,所以在并发队列中优先执行。

主队列

主队列是应用程序启动时,由系统预先创建的,与主线程相关联的队列。我们只能通过系统API来获取主队列,不能手动创建它。下面我们来看看主队列这个串行队列的执行顺序如何:

 dispatch_async(dispatch_get_main_queue(), ^{
  sleep(2);
NSLog(@"main 1");
});

dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"main 2");
});

dispatch_async(dispatch_get_main_queue(), ^{
sleep(1);
NSLog(@"main 3");
});

运行结果如下:


Paste_Image.png

从打印结果可看到执行的顺序是按入队的顺序来执行的。虽然让任务1睡眠2秒再执行,其他任务也只能等待任务1完成,才能继承执行任务2,在任务2执行完成,才能执行任务3。
从打印结果可以看到线程号是固定的,说明都在同一个线程中执行,而这个线程就是主线程。任务只能一个一个地执行。

创建串行队列

通过dispatch_queue_create函数来创建队列,参数一是一个C语言的字符串,是队列的标签,也就是名称,参数二是指定串行队列还是并发队列。
创建串行队列传:DISPATCH_QUEUE_SERIAL(也就是NULL)
创建并发队列传:DISPATCH_QUEUE_CONCURRENT

dispatch_queue_t serialQueue = dispatch_queue_create("serial_queue", 
DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
  NSLog(@"s1");
 });
dispatch_async(serialQueue, ^{
  sleep(2);
  NSLog(@"s2");
});
dispatch_async(serialQueue, ^{
sleep(1);
NSLog(@"s3");
});

打印结果如下:


Paste_Image.png

创建的串行队列只在一个线程运行。

创建并发队列

通过dispatch_queue_create函数来创建队列,参数一是一个C语言的字符串,是队列的标签,也就是名称,参数二是指定串行队列还是并发队列。
创建串行队列传:DISPATCH_QUEUE_SERIAL(也就是NULL)
创建并发队列传:DISPATCH_QUEUE_CONCURRENT
一起来看看串行队列是否需要等待任务执行完成,下一个任务才能开始:

dispatch_queue_t concurrencyQueue = dispatch_queue_create("com.huangyibiao.concurrency-queue",                            
DISPATCH_QUEUE_CONCURRENT);

dispatch_async(concurrencyQueue, ^{
NSLog(@"s1");
});
dispatch_async(concurrencyQueue, ^{
 sleep(2);
 NSLog(@"s2");
});
dispatch_async(concurrencyQueue, ^{
sleep(1);
NSLog(@"s3");
});

打印结果:


Paste_Image.png

从打印结果可以看出来,任务在三个子线程中执行,且互不干扰,不需要等待其他任务完成,就可以并发地分别去执行!

相关文章

  • GCD队列使用

    使用GCD前,先对队列总结一下: 串行和并发 GCD中队列分为两种:串行队列、并发队列。串行队列:任务按在队列里的...

  • GCD串行并发队列

    学习完本篇,您会对以下知识点更加理解: 队列 串行队列 并发队列 GCD全局队列 GCD主队列 创建串行队列 创建...

  • 关于GCD总结

    什么是GCD 理解串行、并发及同步异步 串行和并发 同步和异步 队列 串行队列 两者等效.2)使用主队列(在主队列...

  • GCD串行队列与并发队列

    GCD的队列可以分为2大类型:串行队列、并发队列。一: 串行队列(Serial Dispatch Queue):一...

  • 2021--- GCD

    gcd同步,异步,串行队列,并发队列,全局队列,主队列,以及死锁。 1、gcd队列阻塞问题[https://www...

  • iOS - 多线程(二) GCD讲解

    目录: 1.GCD简介2.串行队列 + 同步执行3.串行队列 + 异步执行4.并发队列 + 同步执行5.并发队列 ...

  • 多线程

    iOS中的几种多线程GCD1、GCD分为任务和队列,任务(同步,异步)队列(串行,并发),同步串行,同步主队列的情...

  • iOS开发多线程之GCD

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

  • 06进阶之路-多线程管理

    1. GCD相关 学习链接 GCD 简介 (多核编程管理线程) GCD 任务和队列(同步和异步任务 并发和串行队列...

  • 队列dispatch_queue的使用

    队列分为:串行队列、并发队列和主队列,主队列也叫特殊串行队列,是GCD自带的。 任务的执行分为:同步执行和异步执行...

网友评论

  • UnitedStates:dispatch_async(dispatch_get_main_queue(), ^{
    sleep(2);
    NSLog(@"main 1");
    });
    主队列的NSLog打印显示并不是你描述的那样,第一张图也显得太模糊了

    dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"main 2");
    });

    dispatch_async(dispatch_get_main_queue(), ^{
    sleep(1);
    NSLog(@"main 3");
    });
  • iOS的Developer:dispatch_queue_t serialQueue = dispatch_queue_create("serial_queue",
    DISPATCH_QUEUE_SERIAL);
    dispatch_async(serialQueue, ^{
    NSLog(@"s1");
    });
    dispatch_async(serialQueue, ^{
    sleep(2);
    NSLog(@"s2");
    });
    dispatch_async(serialQueue, ^{
    sleep(1);
    NSLog(@"s3");
    });

    就凭这个说 串行队列里的异步函数都只在一个线程里执行有点太果断了。我可以证明他不对。
    iOS的Developer:你可以在一个gcd定时器的回调里 添加上面的代码看看
  • 鬼晓晓:正在学习 GCD 对全局并发队列不是很理解 感谢
  • 南栀倾寒:写的挺细 转给新手

本文标题:GCD串行并发队列

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