• 什么是GCD

  Grand Central Dispatch 是Apple开发的一种多核编程技术。主要用于优化应用程序以支持多核处理器以及其他多对称处理系统TA会自动管理线程的生命周期(创建线程、调度任务、销毁线程),完全不需要我们管理,我们只需要告诉干什么就行。同时它使用的也是 c语言,不过由于使用了 Block(Swift里叫做闭包),使得使用起来更加方便,而且灵活。所以基本上大家都使用 GCD 这套方案

  • 什么是任务和队列

  在GCD中有两个非常重要的概念,就是任务和队列

  任务:任务就是一段功能代码,在GCD中一般就是一段block或者函数(block用的比较多),任务有两种执行方式,同步和异步。

  同步和异步的区别就在于是否会阻塞当前线程:

  如果是 同步(sync) 操作,它会阻塞当前线程并等待 Block 中的任务执行完毕,然后当前线程才会继续往下运行。

  如果是 异步(async)操作,当前线程会直接往下执行,它不会阻塞当前线程。

  同步函数无法开启子线程而异步函数有开启子线程的功能。

  队列:用于存放任务,队列一般分为两种,串行队列(SerialQueue)和并行队列(Concurrent),都遵守FIFO。

  队列中的任务根据同步和异步的不同有不同的执行方式:

  

  同步并行,因为同步没有开启子线程的功能,所以并行队列也就失去了并行的效果,一般使用最多的方式就是异步并行。

  

  主队列:这是一个比较特殊的队列,主队列是主线程中的队列,所以不管是异步函数还是同步函数,都不会生成新的分支线程,也就是说异步函数在主队列中丧失了开启线程的能力。TA用于刷新 UI,任何需要刷新 UI 的工作都要在主队列执行,所以一般耗时的任务都要放到别的线程执行。

  •  GCD的使用

  1、异步并发

//1、异步并发(最常用) 开启多条子线程,任务是并发执行的
- (void)asynGlobal {
//获取全局的并发队列
//第一个参数代表队列优先级,如果优先级高,那么这个队列调度的次数就会多一点。通常情况下,这个优先级给默认的优先级
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, );
//一般情况下并行队列使用这个全局的并发队列就行了,不想使用全局队列也可以创建,因为是c函数,所以第一个参数的字符串不要顺手就在前面加个@符号
// dispatch_queue_t queue = dispatch_queue_create("6666", DISPATCH_QUEUE_CONCURRENT);
//将任务添加到并发队列中异步执行
dispatch_async(queue, ^{
NSLog(@"%@-----你484傻-----%d",[NSThread currentThread], [NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"%@------你没吃药吧----%d",[NSThread currentThread], [NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"%@-----能不能去吃药-----%d",[NSThread currentThread], [NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"%@-----滚去吃药-----%d",[NSThread currentThread], [NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"%@-----扑街-----%d",[NSThread currentThread], [NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"%@-----再次扑街-----%d",[NSThread currentThread], [NSThread isMainThread]);
}); //如果是MRC的环境,队列使用完毕之后,需要释放队列
// dispatch_release(queue);
}   //执行效果 如果加入队列的任务太多,为了不消耗过多性能,系统会控制开启的子线程的条数,等有任务执行完了再让剩下的任务继续并行,所以才会有第一条和最后一条是同一个线程的结果。由于是异步函数开启了子线程不是在主线程中,所以[NSThread isMainThread]的值为0
  

  2、异步串行

//异步串行(有时会用) 开启一条子线程,任务在开启的线程中挨个执行
- (void)asynSerial {
//创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("bada.queue", DISPATCH_QUEUE_SERIAL); //将任务添加到串行队列中异步执行
dispatch_async(queue, ^{
NSLog(@"%@-----你484傻-----%d",[NSThread currentThread], [NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"%@------你没吃药吧----%d",[NSThread currentThread], [NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"%@-----能不能去吃药-----%d",[NSThread currentThread], [NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"%@-----滚去吃药-----%d",[NSThread currentThread], [NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"%@-----扑街-----%d",[NSThread currentThread], [NSThread isMainThread]);
}); }
  //从结果就能看出来是在同一条子线程执行的
  

  

  3、同步并发

  

//同步 并发(基本不使用) 如果是同步,在不开启子线程的情况下,并发的效果已经消失了
- (void)synGlobal { //获取全局的并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, );
//将任务添加到并发队列中同步执行
dispatch_sync(queue, ^{
NSLog(@"%@-----你484傻-----%d",[NSThread currentThread], [NSThread isMainThread]);
});
dispatch_sync(queue, ^{
NSLog(@"%@-----你没吃药吧-----%d",[NSThread currentThread], [NSThread isMainThread]);
});
dispatch_sync(queue, ^{
NSLog(@"%@-----能不能吃药-----%d",[NSThread currentThread], [NSThread isMainThread]);
});
dispatch_sync(queue, ^{
NSLog(@"%@-----滚去吃药-----%d",[NSThread currentThread], [NSThread isMainThread]);
});
dispatch_sync(queue, ^{
NSLog(@"%@-----扑街----%d",[NSThread currentThread], [NSThread isMainThread]);
}); }
  //从打印结果就能看出来,由于是同步,并没有开启子线程,都是在主线程执行的,并发的效果也已经没了
  
  •  先来个例子

  当你创建了一个串行队列,先往队列中添加了一个异步任务,然后在异步任务执行的时候又加入了一个同步任务会是什么情况呢?

 - (void)test {
dispatch_queue_t queue = dispatch_queue_create("自己创建的串行队列", DISPATCH_QUEUE_SERIAL);
NSLog(@"11111111 - %@",[NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"3333333333 - %@",[NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"---------- %@",[NSThread currentThread]); });
NSLog(@"----------- %@",[NSThread currentThread]); });
NSLog(@"22222222 - %@",[NSThread currentThread]);
}

  如果你还不太熟悉GCD,对于上面的结果也许会懵圈

  咱们来分析一下上面这段代码的执行顺序,第二行第三行会依次执行这没有问题,碰到第四行有个异步任务,因为是异步会开辟出一个子线程,并不会阻塞当前的线程任务,所以异步block内的内容会放到子线程中执行,跟主线程的任务互相不会干扰。子线程中先执行了第五行的打印,然后碰到了一个同步任务,但是同步会阻塞当前线程的任务往下执行,要先执行了同步block中的内容才能继续往下执行。然而当前只有一条线程,同步任务排在异步任务后面,同步任务要等排在前面一个的异步任务执行完成之后才会执行,这样就出现了两个任务互相等待的情况,这样谁都无法往下执行下去,就出现了卡死的现象,这叫做死锁。

  •  再来个例子

  

   这次是在一个并行队列中先执行了一个异步任务,同样也加入了一个同步任务

 - (void)test1 {
dispatch_queue_t queue = dispatch_queue_create("自己创建的并行队列", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"1111111111111 - %@",[NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"333333333333 - %@",[NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"44444444444444444 - %@",[NSThread currentThread]);
for (int i = ; i < ; i ++) {
NSLog(@"%d, 55555555555555 %@",i, [NSThread currentThread]);
}
dispatch_sync(queue, ^{
NSLog(@"");
});
});
NSLog(@"77777777777777 - %@",[NSThread currentThread]); });
NSLog(@"2222222222222 - %@",[NSThread currentThread]);
}

  你会发现,这次并没有发生上面那种死锁的情况,如果你想不明白了,那么咱们再来分析分析

  首先,还是从主线程开始执行这依然不会有什么问题,第四行的时候遇到了一个异步任务,此时就会开启一条子线程,主线程的任务会继续下去,异步block的代码会在刚开辟的子线程中执行,主线程和子线程的任务是并行的,所以你们执行这段代码的时候出来的打印结果的顺序可能跟我上面的打印结果会有不同。在子线程中,打印完第五行的结果时,碰到了同步任务,这跟第一个例子就有所不同了,由于是在并行队列中,异步任务会挂起,给同步任务让道让TA先执行,执行同步任务的时候又遇到了一个同步任务,当前正在执行的同步任务也会挂起,所以不会发生锁死的现象

  暂结。。。。如果哪里有错误请指教。。。。

多线程之GCD的更多相关文章

  1. iOS多线程之GCD小记

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

  2. iOS 多线程之GCD的使用

    在iOS开发中,遇到耗时操作,我们经常用到多线程技术.Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法,只需定义想要执行的任务,然后添加到适当的调度队列 ...

  3. iOS-多线程之GCD(原创)

    前言 GCD 全称 Grand Central DisPath NSOperation便是基于GCD的封装 基础知识 1.GCD的优势 (1)为多核的并行运算提出了解决方案 (2)GCD会自动利用更多 ...

  4. iOS多线程之GCD详解

    GCD(Grand Central Dispatch)是基于C语言开发的一套多线程开发机制.也是目前苹果官方推荐的多线程开发方法.iOS三种多线程开发中GCD是抽象层次最高的.当然用起来也是最简单的. ...

  5. IOS中的多线程之GCD

    在ios中,使用多线程有三种方式,分别是:NSThread.NSOperation和NSOperationQueue.GCD,在本节,主要讲解一下CDD的使用. GCD(Grand Central D ...

  6. iOS多线程之GCD学习笔记

    什么是GCD 1.全称是Grand Central Dispatch,可译为“牛逼的中枢调度器” 2.纯C语言,提供了非常多强大的函数 GCD的优势 GCD是苹果公司为多核的并行运算提出的解决方案 G ...

  7. IOS 多线程之GCD

    参考:http://www.cnblogs.com/wendingding/p/3806821.html <<Objective-C基础教程>> 第二版 一 简介 GCD 全称 ...

  8. (五十五)iOS多线程之GCD

    GCD的全称为Grand Central Dispatch,翻译为大中央调度,是Apple开发的一个多线程编程解决方法. 进程和线程的概念: 正在进行中的程序被称为进程,负责程序运行的内存分配,每一个 ...

  9. iOS开发多线程之GCD

    Grand Central Dispatch(GCD)是异步执行任务的技术之一.一般将应用程序中记述的线程管理用的代码在系统级中实现.开发者只需要定义想执行的任务并追加到适当的Dispatch Que ...

随机推荐

  1. java自带工具-jps、jinfo、jstack、jstat、jmap

    掌握java自带的这些监控工具,有助与我们很好的分析问题和jvm性能调优秀.收集了些网上整理很好的文章. Java监控工具.调优.调试辅助函数 Java自带的GUI性能监控工具Jconsole以及Ji ...

  2. java反射 cglib asm相关资料

    有篇文章对java反射的调用的效率做了测试,写的比较好.猛击下面地址 http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html ...

  3. Canvas绘图基础(一)

    简单图形绘制 矩形:描边与填充 Canvas的API提供了三个方法,分别用于矩形的清除.描边及填充 clearRect(double x, double y, double w, double h) ...

  4. [django]django+datatable简单运用于表格中

    使用datatable首先需要下载datatable文件,文件主要包括三个文件夹css,img,js相关文件,在django中如何配置呢? 首先需要在模板中引入datatable文件,格式如下: &l ...

  5. Java面向对象 第一章 面向对象开发方法概述

    一.软件开发经历的生命周期: ①软件分析 ②软件设计 ③软件编码 ④ 软件测试 ⑤ 软件部署 ⑥软件维护 二.为了提高软件开发效率,降低软件开发成本,一个优良的软件系统应该具备以下特点: ① 可重用性 ...

  6. ASP.NET CORE dotnet run 命令使用debug方式运行

    由于我的开发环境比较复杂,每次调试一套项目都要启动好几个VS,比较繁琐,今天决定换一种方式调试,对于不该改动的代码的附加项目直接使用dotnet run命令以debug的运行方式运行, 一开始无法运行 ...

  7. Android 从网络中获取数据时 产生部分数据乱码的解决

    产生部分数据乱码的解决 标签: android部分中文乱码 2014-04-12 23:24 12366人阅读 评论(10) 收藏 举报 分类: [Android 基础](15) 版权声明:本文为博主 ...

  8. Python 字符串

    Python访问字符串中的值 Python不支持单字符类型,单字符也在Python也是作为一个字符串使用. Python访问子字符串,可以使用方括号来截取字符串,如下实例: #!/usr/bin/py ...

  9. VS一直停留在“正在还原nuget程序包”

    VS一直停留在“正在还原nuget程序包” 在开发何问起收藏夹的时候,准备在WinFrom中加入网页浏览器,于是下载了一个CEFSharp的源码,生成解决方案的时候,一直提示“正在还原nuget程序包 ...

  10. android开发环境搭建(ubuntu15.04+jdk8+eclipse+android sdk)

    开始学习android开发,首先对其环境对搭建比较重要.平台可以选择window/linux/mac等,这里,我选择ubuntu系统,方法比较原始,当然也可以直接用google提供的android s ...