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. python邮件发送脚本

    转自:http://phinecos.cnblogs.com/ #!/usr/bin/python #coding=utf-8 #@author:dengyike #@date:2010-09-28 ...

  2. Nhibernate初入门基本配置(二)

    转载地址http://www.cnblogs.com/kissdodog/p/3306428.html 使用NHibernate最重要的一步就是配置,如果连NHibernate都还没有跑的起来,谈何学 ...

  3. Problem F: Exponentiation

    Problem F: ExponentiationTime Limit: 1 Sec Memory Limit: 128 MBSubmit: 4 Solved: 2[Submit][Status][W ...

  4. USACO Section 5.3 Big Barn(dp)

    USACO前面好像有类似的题目..dp(i,j)=min(dp(i+1,j),dp(i+1,j+1),dp(i,j+1))+1  (坐标(i,j)处无tree;有tree自然dp(i,j)=0) .d ...

  5. 微信 php 获取ticket

    <?phpheader('content-type:text/html; charset=utf8');define('TOKEN', 'youtoken'); // TOKENdefine(' ...

  6. Git远程仓库的使用(三)

    1)git remote add : 添加远程仓库 git remote add origin git@github.com:用户名.仓库名.git 2) git push –u origin mas ...

  7. Android Studio ADB响应失败解决方法

    当启动Android Studio时,如果弹出 adb not responding. you can wait more,or kill "adb.exe" process ma ...

  8. python 启动简单web服务器

    有时我们在开发web静态页面时,需要一个web服务器来测试. 这时可以利用python提供的web服务器来实现. 1.在命令行下进入某个目录 2.在该目录下运行命令: python -m Simple ...

  9. php订单生成唯一Id

    一般用到一个函数: uniqid(prefix,more_entropy) 参数 描述 prefix 可选.为 ID 规定前缀.如果两个脚本恰好在相同的微秒生成 ID,该参数很有用. more_ent ...

  10. OC学习那些事:点语法

    1.使用自定义的方法创建get/set方法 Person.h文件: #import <Foundation/Foundation.h> @interface Person : NSObje ...