1. 概念

  • GCD:Gtand Central Dispatch 中枢调度器
  • GCD主要解决的是多核并行运算
  • GCD是自动管理线程的生命周期的
1.1 任务
  • 要执行的操作
  • 同步函数:在当前线程中执行任务,不具备开启新线程的能力,立马在当前线程绕那个同步执行任务
  • 异步函数:可以在新的线程中执行任务,具备开启新线程的能力
1.2 队列
  • 用来存放任务
  • 并发队列(异步函数才有效)
  • 串行队列
1.3 一般使用情况
  • 声明一个任务
  • 将任务添加到队列中
    • GCD会自动将队列中的任务取出,放到对应的线程中去
    • 任务要遵循队列的FIFO原则,先进先出,后进后出
使用 并发队列 串行队列 主队列
异步函数 【1】具备开启新线程的能力【2】开启新的线程,任务异步执行 【1】具备开启线程的能力【2】会开线程,开一条线程,队列中的任务是按照先后顺序执行 【1】不会开启新的线程 【2】串行执行
同步函数 【1】不会开启新的线程【2】串行执行任务 【1】不会开启新的线程【2】串行执行任务 【1】如果在主线程中执行会发生死锁【2】在子线程可以

2. 异步函数并发队列

  • 异步函数 :具备开启新线程的能力
  • 异步函数 + 并发队列 ->开新线程,队列中的任务是异步执行
 /*参数一: C语言的字符串,标识符用来区分队列参数二: 队列的类型DISPATCH_QUEUE_CONCURRENT 并发队列DISPATCH_QUEUE_SERIAL 串行队列*///创建一个队列dispatch_queue_t queue = dispatch_queue_create("www.cc.com", DISPATCH_QUEUE_CONCURRENT);//声明任务//第一个参数:队列//要执行的任务// dispatch_async(dispatch_queue_t queue, dispatch_block_t block);dispatch_async(queue, ^{NSLog(@"111111,--%@",[NSThread currentThread]);});

注意: 一个队列中可以.可以添加多个任务,CGD开启线程是不受控制的,不是说有多少个任务就开启多少条线程,具体的是系统内部决定的

3. 异步函数 串行队列

  • 异步函数 :具备开启新线程的能力
  • 异步函数 + 串行队列: 会开线程,开一条线程,队列中的任务是按照先后顺序执行
 //创建串行队列dispatch_queue_t queue = dispatch_queue_create("cc", DISPATCH_QUEUE_SERIAL);//创建异步函数任务dispatch_async(queue, ^{NSLog(@"2222222--%@",[NSThread currentThread]);});dispatch_async(queue, ^{NSLog(@"3333--%@",[NSThread currentThread]);});

其实上面的创建的并发队列,可以换成系统的全局并发队列,区别:上面是自己手动创建的并发队列,下面是获取系统的

//获取全局并发队列dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

4. 同步函数+并发队列

  • 同步函数:不具备开启新线程的能力
  • 同步函数+并发队列:不会开启子线程,串行执行任务
//创建队列dispatch_queue_t queue = dispatch_queue_create("hhh", DISPATCH_QUEUE_CONCURRENT);//创建任务//同步函数dispatch_sync(queue, ^{NSLog(@"999--%@",[NSThread currentThread]);});// 999--<NSThread: 0x60000155a240>{number = 1, name = main}

5. 同步函数+串行队列

  • 同步函数:不具备开启新线程的能力
  • 同步函数+串行队列:不会开启新的线程
 //创建队列dispatch_queue_t queue = dispatch_queue_create("kkk", DISPATCH_QUEUE_SERIAL);//同步函数dispatch_sync(queue, ^{NSLog(@"%@",[NSThread currentThread]);});

6.主队列

  • 主队列是GCD自带的一种比较特殊的串行队列
  • 在主队列中的任务,都是在主线程中执行的
  • 获取主队列 dispatch_get_main_queue()
6.1异步函数+主队列
  • 不会开启子线程
   // 获取主队列dispatch_queue_t queue = dispatch_get_main_queue();//异步函数执行dispatch_async(queue, ^{NSLog(@"%@",[NSThread currentThread]);});
6.2 同步函数 + 主队列
  • 同步函数:不具备开启新线程能力,立马执行如果这个任务没有执行完,不会执行下一个任务
  • 产生:死锁
   // 获取主队列dispatch_queue_t queue = dispatch_get_main_queue();//同步函数执行dispatch_sync(queue, ^{NSLog(@"%@",[NSThread currentThread]);});
6.3 线程产生死锁

造成死锁的条件: 使用同步sync函数 往当前 串行( SERIAL)队列 添加任务, 会卡住当前任务造成死锁

线程死锁
dispatch_sync同步:立马执行当前线程中的任务,执行完毕才能继续往下执行
FIFO原则: 先进的先出

意思就是: 整个函数 viewdidload执行完,打印333,才可以执行 同步的任务 打印222, 由于同步函数sync 要立马执行当前任务,打印222,才可以执行打印333,所以会产生死锁


//MARK:---线程产生死锁
- (void)GCDLock1{//原则: 同步线程 要立马执行// FIFO:先进先出的原则,那个任务 先进来 马哥现任县执行//GCDLock1 在主队列中,要先执行完 这个线程//dispatch_sync 队列要立马在当前线程执行, 所以会产生死锁//打印人3333 要先执行完,才会执行 打印2222,//然而 打印任务2222 要立马执行完,才会执行打印任务3333NSLog(@"11111");dispatch_queue_t que = dispatch_get_main_queue();dispatch_sync(que, ^{NSLog(@"22222");});NSLog(@"333333");}

原因:
1,创建了一个 子线程
2.队列0 和 队列1 都在 子线程中执行
3.由于队列0 执行到 打印执行任务2时,遇到 同步函数,要立马执行函数内 队列1的任务, 此时队列0的打印任务4 还没有执行完, 所以要等打印任务4执行完,才可以执行 同步函数 队列1,造成了线程死锁

// MARK:---会产生死锁2
- (void)GCDLock3 {//会产生死锁// 原因: 1,创建了一个 子线程// 2.队列0 和 队列1 都在 子线程中执行// 3.由于队列0  执行到 打印执行任务2时,遇到 同步函数,要立马执行函数内 队列1的任务, 此时队列0的打印任务4  还没有执行完, 所以要等打印任务4执行完,才可以执行 同步函数 队列1,造成了线程死锁NSLog(@"执行任务1");//DISPATCH_QUEUE_SERIAL 串行队列dispatch_queue_t que = dispatch_queue_create("myque", DISPATCH_QUEUE_SERIAL);dispatch_async(que, ^{  // 线程 队列0NSLog(@"执行任务2");dispatch_sync(que, ^{ //线程 队列1NSLog(@"执行任务3");});NSLog(@"执行任务4");});NSLog(@"执行任务5");
}

7.线程之间的通信

  • 只要是主队列一定是在主线程执行的
- (void)setup7 {//1.获取全局并发队列dispatch_queue_t globalQue = dispatch_get_global_queue(0, 0);//异步函数执行dispatch_async(globalQue, ^{//URLNSURL *url = [NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1559637616849&di=ac9047efc5fb0dbe9eb8d55e321ac4a5&imgtype=0&src=http%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FzfDDxwQnD2Qib4s4tN6tVjeD9TXIedpicIZvKjL1u6MfRicUeAx9t31HLBrh11bfxhbiakH0te22TicfmCZgbErp3Gw%2F640%3Fwx_fmt%3Djpeg"];//回去二进制数据NSData *data = [NSData dataWithContentsOfURL:url];UIImage *image = [UIImage imageWithData:data];//g回到主队列s刷新界面dispatch_async(dispatch_get_main_queue(), ^{NSLog(@"回到主队列");self.imgageView.image = image;});});}

8. GCD任务加强

//任务加强
- (void)demo1{//获取并发队列dispatch_queue_t queue = dispatch_get_global_queue(0, 0);//包装void(^task)(void) = ^{dispatch_sync(queue, ^{NSLog(@"1111---同步--%@",[NSThread currentThread]);});dispatch_async(queue, ^{NSLog(@"2222---异步步--%@",[NSThread currentThread]);});dispatch_async(queue, ^{NSLog(@"33333---异步步--%@",[NSThread currentThread]);});};//执行任务dispatch_async(queue, task);}

9.栅栏函数

栅栏函数是:保证次函数前面的执行完,然后执行自己的栅栏函数,然后在执行 函数后面的线程
注意:
1.全局并发队列,对栅栏函数没有作用
2.使用栅栏函数,必须是自己手动创建的并发队列


//MARK:---栅栏函数- (void)testBary {//群居并发队列
//    dispatch_queue_t que =  dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//自己手动穿件的队列dispatch_queue_t que = dispatch_queue_create("cc", DISPATCH_QUEUE_CONCURRENT);dispatch_async(que, ^{NSLog(@"---%@---1----",[NSThread  currentThread]);});dispatch_async(que, ^{NSLog(@"---%@---2----",[NSThread  currentThread]);});dispatch_barrier_async(que, ^{NSLog(@"-栅栏函数--%@-------",[NSThread  currentThread]);});dispatch_async(que, ^{NSLog(@"---%@---3----",[NSThread  currentThread]);});dispatch_async(que, ^{NSLog(@"---%@---4----",[NSThread  currentThread]);});}

10.同时执行函数 apply

我们知道 for循环是 执行一次循环,在执行下一次循环
有时我们在开发会遇到,多个任务同时执行的问题,比如:同时copy图片到另外一个文件夹中,此时就会用到 apply同时执行函数


- (void)viewDidLoad {[super viewDidLoad];// DISPATCH_QUEUE_PRIORITY_DEFAULT 默认队列dispatch_queue_t que = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//同时执行 并发队列 ,执行10不同的任务dispatch_apply(10, que, ^(size_t index) {NSLog(@"--%zd--%@---",index,[NSThread currentThread]);});}

11.CGD 队列组 - group


- (void)demo1{//创建队列dispatch_queue_t queue = dispatch_get_global_queue(0, 0);//创建任务组dispatch_group_t group = dispatch_group_create();//异步dispatch_group_async(group, queue, ^{NSLog(@"AAAA");});//异步dispatch_group_async(group, queue, ^{NSLog(@"bbbb");});//异步dispatch_group_async(group, queue, ^{NSLog(@"CCCC");});// 就是保证上面的3个任务 执行完毕 之后才执行  dispatch_group_notify//这个任务组完成的通知dispatch_group_notify(group, queue, ^{NSLog(@"所有的任务完成");});NSLog(@"11111");
}

12 .常用的函数

12.1一次性执行函数

//MARK:---一次性执行函数
- (void)testOnce{static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{NSLog(@"执行一次就b在执行了");});
}

12.2 常用的代码执行 延迟操作

//MARK:---延迟执行
- (void)testDiplay{//延迟2l秒执行[self performSelector:@selector(run) withObject:nil afterDelay:2.0];//延迟3秒执行[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(run) userInfo:nil repeats:NO];dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{NSLog(@"延迟4秒执行");});}- (void)run {NSLog(@"奔跑");
}

iOS之线程(二)GCD相关推荐

  1. iOS多线程开发之GCD(基础篇)

    总纲: GCD基本概念 GCD如何实现 GCD如何使用 队列和任务组合 一.GCD基本概念 GCD 全称Grand Central Dispatch(大中枢队列调度),是一套低层API,提供了⼀种新的 ...

  2. ios查看线程数量_iOS多线程进阶

    .一.进程 进程:是指在系统中正在运行的一个应用程序,每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开迅雷.Xcode,系统就会分别启动2个进程 二.线程 1.什么是线程 ...

  3. iOS 多线程:『GCD』详尽总结

    原文链接:www.jianshu.com/p/2d57c7201- 感谢大家对这篇文章的喜欢和支持.为了不辜负大家的喜欢,也为了更好的让大家了解 iOS 多线程,以及 GCD 的相关知识,我对这篇文章 ...

  4. iOS多线程之GCD小记

    iOS多线程之GCD小记 iOS多线程方案简介 从各种资料中了解到,iOS中目前有4套多线程的方案,分别是下列4中: 1.Pthreads 这是一套可以在很多操作系统上通用的多线程API,是基于C语言 ...

  5. iOS原生实现二维码扫描

    iOS原生实现二维码扫描 最近项目上需要开发扫描二维码进行签到的功能,主要用于开会签到的场景,所以为了避免作弊,我们再开发时只采用直接扫描的方式,并且要屏蔽从相册读取图片,此外还在二维码扫描成功签到时 ...

  6. ios内购二次验证安全性问题_苹果IOS内购二次验证返回state为21002的坑

    项目是三四年前的老项目,之前有IOS内购二次验证的接口,貌似很久都没用了,然而最近IOS的妹子说接口用不了,让我看看啥问题.接口流程时很简单的,就是前端IOS在购买成功之后,接收到receipt后进行 ...

  7. iOS相册图片二维码识别

    前言:最近客户要求开发一个功能,类似微信长按图片识别图片中的二维码,一开始我使用了ZXingObjC,但是完成后被测试出有些二维码识别不了,所以只能另寻它法,之后更换为苹果系统自带的识别图片二维码的功 ...

  8. Ios子线程渲染Opengl

    1. 介绍 ios并没有像Android glsurfaceview或者Qt QOpenglWidget 那样完整Opengl渲染View封装,官方demo也是主线程创建的CADisplayLink提 ...

  9. 小米手环iOS开发实战(二):开发Demo让你的手环振动起来

    小米手环iOS开发实战(二):开发Demo让你的手环振动起来 上一节讲了CoreBluetooth的使用,理论知识很枯燥,那么现在先利用上一节讲的内容,做一个简易手环应用,实现连接/断开手环,查看手环 ...

  10. 苹果宣布iOS切分为二独立出iPadOS操作系统

    2019独角兽企业重金招聘Python工程师标准>>> 在开发者大会WWDC 2019上,苹果宣布将把iOS切分为二,独立出专为iPad设计的操作系统iPadOS,改版主屏幕(Hom ...

最新文章

  1. 微软云计算 Windows Azure“腾云驾雾”
  2. php----http协议 Cookie
  3. 从一个数组中提取出第start位到第end位
  4. 思科计算机网络第四章考试,思科网络学院第期第四章.docx
  5. 海康服务器协议,国标流媒体服务器GB28181协议和海康设备的交互过程记录
  6. tcping要安装什么工具linux,Linux下的TCP测试工具——TCPING安装简明教程
  7. 华为OSPF多区域配置实例
  8. -XX:SoftRefLRUPolicyMSPerMB参数了解
  9. 小技巧分享:Sourcetree 免登录注册破解教程
  10. python re subn_python中的正则re.sub re.subn
  11. HTML——携程旅游案例
  12. html画布实现小球沿直线下落,js+html5实现的自由落体运动效果代码
  13. CocosCreator 计时器
  14. 关于制备螯合效应之冠醚修饰酚醛/硝酸铽/聚硫醚/苯并-18-冠醚-6的过程分享
  15. 50个极具创意和灵感的404页面
  16. 笔记本电脑无法连接WLAN网络(适配器Intel(R) Wireless-AC 9461 ) 错误代码10
  17. 【技术美术图形部分】PBR直接光部分:Disney原则的BRDF和次表面散射模型
  18. IDEA无法使用已安装的字体
  19. bootstrap之collapse(折叠)
  20. android联想功能介绍,在Android世界中联想推出了功能强大的手机Z5 Pro GT

热门文章

  1. abcde类 ip地址_IP寻址基础,让你了解IP地址ABCDE类的区分
  2. Java 二分排序法
  3. android 反编译全套工具
  4. 蝙蝠算法c语言,求解0-1背包问题的二进制蝙蝠算法
  5. AB PLC 1769_L24ER_QB1B新机测试固件下载-程序下载
  6. MindMaster for Mac(亿图思维导图)
  7. 三大协议NetBEUI和 IPX/SPX TCP/IP
  8. 软件测试日志怎么写,为什么要进行日志测试和如何进行日志测试?
  9. [MLDN魔乐科技]Oracle视频教程
  10. 数学建模——matlab基本使用