GCD

 1> 概述

  • Grand Central Dispatch (GCD)是Apple开发的一种多核编程技术。主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。

  • GCD提供函数实现多线程开发,性能更高,功能也更加强大。

  • 它首次发布在Mac OS X 10.6 ,iOS 4及以上也可用。

 2> 核心概念

  • 任务:具有一定功能的代码段。一般是一个block或者函数

  • 分发队列:GCD以队列的方式进行工作,FIFO

  • GCD会根据分发队列的类型,创建合适数量的线程执行队列中的任务

 3> GCD中的队列

  • 串行队列(SerialQueue):一次只执行一个任务。Serial queue通常用于同步访问特定的资源或数据。当你创建多个Serial queue时,虽然它们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。SerialQueue能实现线程同步

  • 并行队列(Concurrent):可以并发地执行多个任务,虽然遵守FIFO(先进先出),但由于各个任务被分配到不同的线程执行,因此其完成时间有可能不同,即:后分配的任务有可能先执行完成;并发队列一定需要和异步执行的任务(使用dispatch_async())结合起来使用才有意义。

  • 主队列:主队列也是一个串行队列,主队列中的任务都在主线程中执行。

 4> 串行队列(SerialQueue)

  • 第一种:系统提供的创建串行队列的方法,实际上主队列的创建方法
 // 第一种获取方式:里面的任务是在主线程依次去执行,dispatch_get_main_queue()获取主队列
dispatch_queue_t queue = dispatch_get_main_queue();
// 往队列里面添加任务
dispatch_async(queue, ^{
NSLog(@"这是第一个任务,当前线程是:%@, 是否主线程 :%d ", [NSThread currentThread], [[NSThread currentThread] isMainThread]);
});
  • 第二种:自己创建的队列
 // 参数1:队列的名字(苹果推荐使用反向域名去命名)
// 参数2:队列的类型(串行队列、并行队列),这种方式创建的队列,它会自己去开辟一个子线程去完成队列里面的任务
dispatch_queue_t queue = dispatch_queue_create("com.zf.mySerialQueue", DISPATCH_QUEUE_SERIAL); dispatch_async(queue, ^{
NSLog(@"这是第一个任务,当前线程是:%@, 是否主线程 :%d ", [NSThread currentThread], [[NSThread currentThread] isMainThread]);
});

5> 并行队列

  • 第一种:系统提供的创建并行队列的方法
 // 参数1:优先级PRIORITY(有四个,没有明显的区别)
// 参数2:系统保留字,苹果预留的参数为了以后去使用,目前没有用到,填写0
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, ); dispatch_async(oneQueue, ^{
NSLog(@"这是第一个任务。。。线程是:%@, 是否主线程:%d", [NSThread currentThread], [[NSThread currentThread] isMainThread]);
});
  • 第二种:自己创建的队列

  使用的方法同串行队列,只有创建函数参数2给定队列的类型的时候,将DISPATCH_QUEUE_SERIAL替换为DISPATCH_QUEUE_CONCURRENT

 // 参数1:队列的名字(苹果推荐使用反向域名去命名)
// 参数2:队列的类型(串行队列、并行队列),这种方式创建的队列,它会自己去开辟一个子线程去完成队列里面的任务
dispatch_queue_t queue = dispatch_queue_create("com.zf.mySerialQueue", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{
NSLog(@"这是第一个任务,当前线程是:%@, 是否主线程 :%d ", [NSThread currentThread], [[NSThread currentThread] isMainThread]);
});

6> GCD功能函数

  • dispatch_async(dispatch_queue_t queue, ^(void)block)    // 异步任务,往队列中添加任务,任务会排队执行

  参数1(dispatch_queue_t queue):添加任务的队列

  参数2(^(void)block):Block,主要是在添加过程中进行一些操作,操作代码就写在Block中

  • dispatch_after()      //往队列中添加任务,任务不但会排队,还会在延迟的时间点执行
 /*
函数
dispatch_after(dispatch_time_t when, dispatch_queue_t queue, ^(void)block); // 系统封装的代码快(一般使用)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(具体的浮点型数字 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  延迟执行的内容
}); */
// 参数1:延迟的时间,使用dispatch_time()初始化
// 参数2:队列
// 参数3:Block
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"3.0秒后");
});

  dispatch_time(dispatch_time_t when, int64_t delta)对延迟时间进行初始化

  参数1:为起始时间,系统宏定义,一般使用 DISPATCH_TIME_NOW

  参数2:为延迟的具体时间类型为 int64_t,变量的类型为:具体浮点型数字 * 时间单位(系统的宏定义,可以根据实际情况选用)

  • dispatch_apply()    //往队列中添加任务,任务会重复执行n次
 /*
dispatch_apply(size_t iterations, dispatch_queue_t queue, ^(size_t) {
code
});
*/
dispatch_queue_t queue = dispatch_queue_create("com.zf.myQueue", DISPATCH_QUEUE_CONCURRENT);
// 参数1:添加任务的个数
// 参数2:队列
// 参数3:Block,这个Block没有变量名,需要自己添加
dispatch_apply(, queue, ^(size_t index) {
NSLog(@"%zu", index);
});

:函数dispatch_apply()的参数3Block没有变量名,需要自己添加

  • dispatch_group_async()   //将任务添加到队列中,并添加分组标记

  • dispatch_group_notify()    //将任务添加到队列中,当某个分组的所有任务执行完之后,此任务才会执行

  •  //    dispatch_group_t主要用于把一些不相关的任务归为一组
    // 组里面放的是队列
    // dispatch_group_async作用是往组里面的队列添加任务
    // dispatch_group_notify作用:监听组里面的任务,等到组里面的任务全部执行完成之后,才会执行它里面的任务 //1、创建队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,);
    //2、创建组
    dispatch_group_t group = dispatch_group_create();
    // 3、往组里面的队列添加任务(注意:在执行notify之前最起码要向队列中放置一个任务才可以,否则,notify里面的任务不会等待小组里面的其他任务执行完才执行。)
    dispatch_group_async(group, queue, ^{
    NSLog(@"这是第一个任务。。。线程是:%@, 是否主线程:%d", [NSThread currentThread], [[NSThread currentThread] isMainThread]);
    }); dispatch_group_notify(group, queue, ^{
    NSLog(@"我是最后一个任务,组里面的其他任务都执行完毕之后,我就会执行");
    });
  • dispatch_barrier_async()  //将任务添加到队列中,此任务执行的时候,其他任务停止执行
 // 数据库的读取。。。可以并发执行,通过 GCD 里面的并行队列去实现
// 数据库的写入。。。。只能串行执行,通过 GCD 里面的串行队列去实现
// 但是真正的项目,肯定是既有数据的读取,也有数据库的写入。。。如何解决该问题:dispatch_barrier_async 在它之前的任务可以并发去执行,在他之后的任务也可以去并发执行
dispatch_queue_t queue = dispatch_queue_create("concurrentTest",DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"这是第一个读取数据的任务。。。线程是:%@, 是否主线程:%d", [NSThread currentThread], [[NSThread currentThread] isMainThread]);
}); dispatch_barrier_async(queue, ^{
NSLog(@"正在在数据库里写东西,不要打扰我");
}); dispatch_async(queue, ^{
NSLog(@"这是第二个读取数据的任务。。。线程是:%@, 是否主线程:%d", [NSThread currentThread], [[NSThread currentThread] isMainThread]);
});
  • dispatch_once()   //任务添加到队列中,但任务在程序运行过程中,只执行一次

  dispatch_once: 该函数接收一个dispatch_once用于检查该代码块是否已经被调度的谓词(是一个长整型,实际上作为BOOL使用)。它还接收一个希望在应用的生命周期内仅被调度一次的代码块。

  dispatch_once 不仅意味着代码仅会被运行一次,而且还是线程安全的,这就意味着你不需要使用诸如@synchronized之类的来防止使用多个线程或者队列时不同步的问题。

  运用代码(单例的完整定义)

 static MyHandle *handle = nil;

 + (MyHandle *)sharedMyHandle
{
// 在GCD中只执行一次,用于记录内容是否执行过
static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{
handle = [MyHandle new];
}); return handle;
}
  • dispatch_sync()   //同步任务 将任务添加到队列中,block不执行完,下面代码不会执行

  与 dispatch_async() 的区别:

   dispatch_async() 不等 block 体执行完,就去执行下面的代码,会在另外的线程中执行

   dispatch_sync() 会等待 block 体执行完成之后,才会去执行 block 体外面的代码,会在当前的线程中执行,当前线程有可能是主线程,也有可能是子线程

  • dispatch_async_f()  //将任务添加到队列中,任务是函数非block
 // 函数
void function(void * str){
NSLog(@"这是一个函数,%s",str);
} // 第一个参数:队列
// 第二个参数:函数参数的内容
// 第三个参数:函数
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, );
dispatch_async_f(queue, @"passValue", function);

第四种:GCD的更多相关文章

  1. iOS多线程全套:线程生命周期,多线程的四种解决方案,线程安全问题,GCD的使用,NSOperation的使用

    目的 本文主要是分享iOS多线程的相关内容,为了更系统的讲解,将分为以下7个方面来展开描述. 多线程的基本概念 线程的状态与生命周期 多线程的四种解决方案:pthread,NSThread,GCD,N ...

  2. iOS-UITextField中给placeholder动态设置颜色的四种方法

    思路分析: 0.自定义UITextField 1.设置占位文字的颜色找-->placeholderColor,结果发现UITextField没有提供这个属性 2.在storyboard/xib中 ...

  3. iOS 中 延迟操作四种方式

    本文列举了四种延时执行某函数的方法及其一些区别.假如延时1秒时间执行下面的方法. - (void)delayMethod { NSLog(@"execute"); } 1.perf ...

  4. iOS多线程编程(四)------ GCD(Grand Central Dispatch)

    一.简单介绍 是基于C语言开发的一套多线程开发机制.也是眼下苹果官方推荐的多线程开发方法.用起来也最简单.仅仅是它基于C语言开发,并不像NSOperation是面向对象的开发.而是全然面向过程的.假设 ...

  5. 两个变量交换的四种方法(Java)

    对于两种变量的交换,我发现四种方法,下面我用Java来演示一下. 1.利用第三个变量交换数值,简单的方法. (代码演示一下) class TestEV //创建一个类 { public static ...

  6. Android开发之基本控件和详解四种布局方式

    Android中的控件的使用方式和iOS中控件的使用方式基本相同,都是事件驱动.给控件添加事件也有接口回调和委托代理的方式.今天这篇博客就总结一下Android中常用的基本控件以及布局方式.说到布局方 ...

  7. TCP四种计时器

    TCP共使用以下四种计时器,即重传计时器.坚持计时器.保活计时器和时间等待计时器 .这几个计时器的主要特点如下:      1.重传计时器      当TCP发送报文段时,就创建该特定报文段的重传计时 ...

  8. C++四种类型转换方式。

    类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单(TYPE)EXPRESSION,但是c风格的类型转换有不少的缺点,有的时候用c风格的转换是不合适的,因为它可以在任意类型之间转换,比 ...

  9. C#批量插入数据到Sqlserver中的四种方式

    我的新书ASP.NET MVC企业级实战预计明年2月份出版,感谢大家关注! 本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的 ...

  10. 织梦DedeCMS模板防盗的四种方法

    织梦(DedeCMS)模板也是一种财富,不想自己辛辛苦苦做的模板被盗用,在互联网上出现一些和自己一模一样的网站,就需要做好模板防盗.本文是No牛收集整理自网络,不过网上的版本都没有提供 Nginx 3 ...

随机推荐

  1. iOS 切割图片

    - (UIImage *)CutImageWithImage:(UIImage *)image withRect:(CGRect)rect { //使用CGImageCreateWithImageIn ...

  2. java思考题

    1.仔细阅读示例: EnumTest.java,运行它,分析运行结果? 你能得到什么结论?你掌握了枚举类型的基本用法了吗? public class EnumTest { public static ...

  3. HDU 2841 Visible Trees(莫比乌斯反演)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2841 题意:给n*m的矩阵(从(1,1)开始编号)格子,每个格子有一棵树,人站在(0,0)的位置,求可 ...

  4. KMP算法番外篇--求解next数组

    KMP算法实现字符串的模式匹配的时间复杂度比朴素的模式匹配好很多,但是它时间效率的提高是有前提的,那就是:模式串的重复率很高,不然它的效率也不会凸显出来.在实际的应用中,KMP算法不算是使用率很高的一 ...

  5. Myeclipse安装Activiti

    1.将压缩包内activiti文件夹放入Myeclipse\dropins文件夹内并修改activiti文件夹内Link文件指向自己的目录重启Myeclipse(这时打开bpmn文件仍会报错).2.将 ...

  6. Sql:查看数据库表和表结构的语句

    T-sql 显示表结构和字段信息的sql语句: exec sp_help tablename; ~~使用存储过程 sp_help 显示数据库包含哪些表的sql语句: use yourDBname;se ...

  7. 什么是PCB改板及PCB改板应注意的问题

    PCB改板是指在保持原有功能一致的前提下,对原有产品设计及电路板布局走线设计的基础上进行整改设计,调整板上器件布局与线路走向,实现电子产品重新设计研发,同时又可以规避知识产权等纠纷,加快新产品研发速度 ...

  8. c++builder 重载WindowProc、WndProc 截获消息(比Delphi多一个Message Map方法)

    c++builder 重载WindowProc.WndProc 截获消息 方法一WindowProc void __fastcall  myWindowProc(Messages::TMessage ...

  9. HDU 1090 A+B for Input-Output Practice (II)

    #include <cstdio> int main() { int n,a,b; scanf("%d",&n); ; i<=n; i++) { scan ...

  10. BZOJ 3389: [Usaco2004 Dec]Cleaning Shifts安排值班

    题目 3389: [Usaco2004 Dec]Cleaning Shifts安排值班 Time Limit: 1 Sec  Memory Limit: 128 MB Description      ...