GCD使用总结

GCD使用总结

看了MJ大神的视频与几篇播客深入了解GCD:Part 1/2 深入了解GCD:Part 2/2 GCD使用经验与技巧浅谈之后,自己总结的使用注意

任务

GCD中要执行的操作都可以叫做任务(下载图片、下载文本等)


队列

按照FIFO(先进先出)的顺序帮我们调度任务,GCD会把我们添加到队列中的任务取出,放到线程中执行。队列分为

串行队列

串行队列同一时间只能有一个任务执行,后一个任务只有在前一个任务执行完之后才能被调度到线程中执行

并行队列

并行队列同一时间可以多个任务执行,后一个任务不需要等前一个任务执行完,就可以被调度


任务的提交

任务提交的方式会决定要不要开启新的线程,在GCD中将任务添加到队列中有两种方式

同步提交

将任务同步提交给队列,不会开启新的线程,只会在当前线程执行,并且只有在同步任务执行完之后,才能继续向下执行代码,同步提交的方式:

1 dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

异步提交

任务被异步提交给队列,会开启新的线程,但开多少新的线程,我们不能决定,由系统自己决定,并且不需要等异步任务执行完,就可以继续向下执行代码,异步提交的方式:

1 dispatch_async(dispatch_queue_t queue, dispatch_block_t block);


GCD中不同的提交方式与不同队列的组合

串行队列同步提交

1 dispatch_queue_t queue = dispatch_queue_create("com.yys.test", DISPATCH_QUEUE_SERIAL);
2
3 dispatch_sync(queue, ^{
4
5   // 下载文件,图片等资源
6
7 });

首先根据同步提交 -> 没有新的线程开启

然后根据串行队列的特点 -> 同一时间只能执行一个任务

最终得到 -> 不会开启新的线程,任务按照提交顺序在当前线程依次执行

串行队列异步提交

1 dispatch_queue_t queue = dispatch_queue_create("com.yys.test", DISPATCH_QUEUE_SERIAL);
2
3 dispatch_async(queue, ^{
4
5   // 下载文件,图片等资源
6
7 });

根据异步提交 -> 会有新的线程开启

根据串行队列的特点 -> 同一时间只能执行一个任务

最终得到 -> 会开启新的线程,任务在新开启的线程中按照提交顺序依次执行,但是仅仅只会开启一条新的线程,因为异步提交会开启新的线程,但是串行队列只需要一条线程就可以执行所有提交的任务

并行队列同步提交

1 dispatch_queue_t queue = dispatch_queue_create("com.yys.test", DISPATCH_QUEUE_CONCURRENT);
2
3 dispatch_sync(queue, ^{
4
5   // 下载文件,图片等资源
6
7 });

根据同步提交 -> 没有新的线程开启

并行队列 -> 同一时间可以有多个任务被调度,但是在同步提交的条件下,并行队列失去了并行的能力,与串行队列区别不大

最终得到 -> 不会开启新的线程,提交的任务在当前线程按照提交顺序依次执行

并行队列异步提交

1 dispatch_queue_t queue = dispatch_queue_create("com.yys.test", DISPATCH_QUEUE_CONCURRENT);
2
3 dispatch_async(queue, ^{
4
5   // 下载文件,图片等资源
6
7 });

异步提交 -> 可以开启新的线程

并行队列 -> 同一时间可以有多个任务被调度

最终得到 -> 有新的线程开启,可以多个任务同时执行,会开多条线程,但是开多少条线程我们不能控制。所以,可以用来同时下载多张图片


GCD中特别的队列 -> 主队列(串行队列)

主队列是串行队列,它的主要作用就是用来更新UI控件,所有UI控件的刷新都必须在主线程中执行

主队列同步提交(尤其注意)

1 dispatch_queue_t queue = dispatch_get_main_queue();
2
3 dispatch_sync(queue, ^{
4
5   // 下载文件,图片等资源
6
7 });

主队列同步提交任务一定会发生死锁,就是线程被阻塞,不会再继续向下执行代码

同步提交使用时尤其注意,不能在当前线程再向这个线程中提交任务

主线程在执行 任务A ,在 任务A 中向主队列中添加 任务B ,这时 任务B 会在主线程中执行,由于主队列是串行队列,所以任务会依次执行, 任务A 执行完就会执行 任务B ,但是 任务A 要执行完则 任务B 必须也要执行完,但是 任务B 要等 任务A 执行完才能执行,因此会发生死锁,代码不会向下执行

主队列异步提交

1 dispatch_queue_t queue = dispatch_get_main_queue();
2
3 dispatch_async(queue, ^{
4
5   // 下载文件,图片等资源
6
7 });

这一情况也是很特殊的,尽管是异步提交,但是没有新的线程开启,GCD会在恰当的时候把你提交的任务在主线程中执行完,执行的时刻不可控


GCD的其他用处

dispatch_after: 延后执行

1 dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(需要延后的时间 * NSEC_PER_SEC));
2
3 dispatch_after(time, dispatch_get_main_queue(), ^{
4
5   // 需要延后执行的代码
6
7 });

需要注意的是,这里并不是在某一个时刻执行任务,只是将任务提交给队列

 1 NSLog(@"线程执行开始");
 2
 3 dispatch_async(dispatch_get_main_queue(), ^{
 4
 5   [NSThread sleepForTimeInterval:10.];
 6
 7 });
 8
 9 dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5. * NSEC_PER_SEC));
10
11 dispatch_after(time, dispatch_get_main_queue(), ^{
12
13   NSLog(@"延后提交任务”);
14
15 });

执行结果

这里第二次打印是在第一次打印10秒之后,并不是5秒之后

dispatch_once: 只执行一次某段代码

1 static dispatch_once_t onceToken;
2
3 dispatch_once(&onceToken, ^{
4
5   // 只需要执行一次的代码
6
7 });

需要注意的是onceToken一定要用static申明,这样才能保证需要执行一次的代码执行一次,否则的话,不能保证代码只执行一次,会出现难以修复的bug

dispatch_group

使用场景:当你执行多个异步任务,并且要等到所有的任务执行完做某些操作时

 1 dispatch_group_t group = dispatch_group_create();
 2
 3 dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
 4
 5   // 提交任务A
 6
 7 });
 8
 9 dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
10
11   // 提交任务B
12
13 });
14
15 dispatch_group_notify(group, dispatch_get_main_queue(), ^{
16
17   // 所有任务执行完后,所需要的操作
18
19 });

这里有两种方式通知所有的任务完成:

  1. dispatch_group_notify 这一种是异步通知,不会阻塞当前线程(常用)
  2. dispatch_group_wait 这一种会一直等待,直到所有的任务完成或者超时

dispatch_barrier_sync和dispatch_barrier_async

1 dispatch_barrier_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
2
3   // 提交任务
4
5 });

这两个函数提交的任务,在执行时会阻塞后面的任务,在这一时间内,只有这一任务在执行,后续任务只有在这个任务执行完成后才能执行,并且所有在这个任务之前的任务一定会先于这个任务完成

dispatch_barrier_sync和dispatch_barrier_async只在自己创建的并发队列上有效,在全局并发队列、串行队列上,效果跟dispatch_sync、 dispatch_async效果一样

时间: 2024-10-06 19:15:20

GCD使用总结的相关文章

dutacm.club 1094: 等差区间(RMQ区间最大、最小值,区间GCD)

1094: 等差区间 Time Limit:5000/3000 MS (Java/Others)   Memory Limit:163840/131072 KB (Java/Others)Total Submissions:655   Accepted:54 [Submit][Status][Discuss] Description 已知一个长度为 n 的数组 a[1],a[2],-,a[n],我们进行 q 次询问,每次询问区间 a[l],a[l+1],-,a[r?1],a[r] ,数字从小到大

iOS GCD中级篇 - dispatch_group的理解及使用

前文我们讲了GCD基础篇,以及同步.异步,并发.并行几个概率的理解. 参考链接: iOS GCD基础篇 - 同步.异步,并发.并行的理解 现在讲一下dispatch_group的概念以及几种场景下的使用 1.关于dispatch_group 把一组任务提交到队列中,这些队列可以不相关,然后监听这组任务完成的事件. 最常见的几个方法: 1.dispatch_group_create创建一个调度任务组 2.dispatch_group_async 把一个任务异步提交到任务组里 3.dispatch_

转 GCD

GCD 深入理解:第一部分 本文翻译自 http://www.raywenderlich.com/60749/grand-central-dispatch-in-depth-part-1 原作者:Derek Selander 译者:@nixzhu 虽然 GCD 已经出现过一段时间了,但不是每个人都明了其主要内容.这是可以理解的:并发一直很棘手,而 GCD 是基于 C 的 API ,它们就像一组尖锐的棱角戳进 Objective-C 的平滑世界.我们将分两个部分的教程来深入学习 GCD . 在这两

GCD多线程死锁总结

// //  ViewController.m //  多线程 // // #import "ViewController.h" @interface ViewController () @end @implementation ViewController /* >1 队列和线程的区别: 队列:是管理线程的,相当于线程池,能管理线程什么时候执行. 队列分为串行队列和并行队列 串行队列:队列中的线程按顺序执行(不会同时执行) 并行队列:队列中的线程会并发执行,可能会有一个疑问,队

GCD 常用操作

GCD多线程操作 1)用得最多的操作 //获取全局队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //异步执行 dispatch_async(queue, ^{ //下载图片 dispatch_async(dispatch_get_main_queue(), ^{ //回到主线程更新UI }); }); ? 2)延时执行 1-调用NSObject方法 [Self

GCD

Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法. dispatch queue分成以下三种: 1)运行在主线程的Main queue,通过dispatch_get_main_queue获取. /*! * @function dispatch_get_main_queue * * @abstract * Returns the default queue that is bound to the main thread. * * @discussi

iOS开发——多线程OC篇&GCD实用总结

GCD实用总结 图片下载 注:iOS开发中常见GCD的实用也就这些了, 先来看看之前我们经常使用的方式: 1 static NSOperationQueue * queue; 2 3 - (IBAction)someClick:(id)sender { 4 self.indicator.hidden = NO; 5 [self.indicator startAnimating]; 6 queue = [[NSOperationQueue alloc] init]; 7 NSInvocationO

猫猫学iOS(五十二)多线程网络之GCD下单例设计模式

猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243?viewmode=contents 单例模式 1:单例模式的作用 可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问 从而方便地控制了实例个数,并节约系统资源 单例模式的使用场合 在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次) 简单来说,就是我弄了一个工具类,他就有一份,比如我设计了一个音乐播放器NYPlayer,这个播放器类我

iOS 开发之多线程之GCD

1.GCD(Grand Centrol Dispath) 并行:宏观以及微观都是两个人再拿着两把铁锹在挖坑,一小时挖两个大坑 并发:宏观上是感觉他们都在挖坑,微观是他们是在使用一把铁锹挖坑,一小时后他们挖了两个小坑. 总结:就单个cpu来说,大部分进程是并发进行的,就是一把铁锹,你一下我一下,只是间隔时间较短,用户感觉不到而已. 应用: GCD包括: (1)实际使用中 //dispatch_get_global_queue(0, 0)第一个0是优先级,第二个保留字段 dispatch_async

hdu 4497 GCD and LCM

GCD and LCM Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 1092    Accepted Submission(s): 512 Problem Description Given two positive integers G and L, could you tell me how many solutions of (