GCD(Grand Central Dispatch)是基于C语言开发的一套多线程开发机制。也是目前苹果官方推荐的多线程开发方法。iOS三种多线程开发中GCD是抽象层次最高的。当然用起来也是最简单的。只是它基于C语言开发。并不像NSOperation是面向对象的开发。而是完全面向过程的。这种机制相比较于前面两种多线程开发方式最明显的优点就是它对于多核运算更佳有效。

GCD中也有一个类似于NSoperationQueue的队列,GCD统一管理整个队列中的任务。但是GCD中的队列氛围并行队列和串行队列两类。

  串行队列:只有一个线程,加入到队列中的操作按添加顺序依次执行。

  并发队列:有多个线程,操作进来之后他会将这些队列安排到可用的处理器上。同时保证先进来的任务优先处理。

其实在GCD中还有一个特殊的队列就是主队列,用来执行主线程上的操作任务。(从前面的演示中可以看到其实在NSOperation中也有一个主队列)

串行队列

使用串行队列时首先要创立一个串行队列,然后调用异步调用方法,在此方法中传入串行队列和线程操作即可自动执行。下面就是一个例子。

  1. #define ROW_COUNT 5
  2. #define COLUMN_COUNT 3
  3. #define ROW_HEIGHT 100
  4. #define ROW_WIDTH ROW_HEIGHT
  5. #define CELL_SPACING 10
  6.  
  7. @interface ViewController () {
  8. NSMutableArray *_imageViews;
  9. NSMutableArray *_imageNames;
  10. }
  11.  
  12. @end
  13.  
  14. @implementation ViewController
  15.  
  16. - (void)viewDidLoad {
  17. [super viewDidLoad];
  18.  
  19. [self layoutUI];
  20. }
  21.  
  22. - (void)layoutUI {
  23. _imageViews = [NSMutableArray array];
  24. for (int r=; r<ROW_COUNT; r++) {
  25. for (int c=; c<COLUMN_COUNT; c++) {
  26. UIImageView *imageView=[[UIImageView alloc]initWithFrame:CGRectMake(c*ROW_WIDTH+(c*CELL_SPACING), r*ROW_HEIGHT+(r*CELL_SPACING ), ROW_WIDTH, ROW_HEIGHT)];
  27. imageView.contentMode=UIViewContentModeScaleAspectFit;
  28. // imageView.backgroundColor=[UIColor redColor];
  29. [self.view addSubview:imageView];
  30. [_imageViews addObject:imageView];
  31.  
  32. }
  33. }
  34.  
  35. UIButton *button=[UIButton buttonWithType:UIButtonTypeRoundedRect];
  36. button.frame=CGRectMake(, , , );
  37. [button setTitle:@"加载图片" forState:UIControlStateNormal];
  38. //添加方法
  39. [button addTarget:self action:@selector(loadImageWithMultiThread) forControlEvents:UIControlEventTouchUpInside];
  40. [self.view addSubview:button];
  41.  
  42. //创建图片链接
  43. _imageNames=[NSMutableArray array];
  44. for (int i=; i<ROW_COUNT*COLUMN_COUNT; i++) {
  45. [_imageNames addObject:[NSString stringWithFormat:@"http://images.cnblogs.com/cnblogs_com/kenshincui/613474/o_%i.jpg",i]];
  46. }
  47.  
  48. }
  49.  
  50. - (void)loadImageWithMultiThread {
  51. int count = ROW_COUNT * COLUMN_COUNT;
  52. //创建一个串行队列
  53. /*
  54. 第一个参数是 队列名称
  55. 第二个参数是 队列类型
  56. */
  57. //注意 dispatch_queue_t的对象不是指针类型
  58. dispatch_queue_t serialQueue = dispatch_queue_create("mySeriQueuw", DISPATCH_QUEUE_SERIAL);
  59. //创建多个线程用于填充图片
  60. for (int i = ; i < count; i++) {
  61. //异步执行队列任务
  62. dispatch_async(serialQueue, ^{
  63. [self loadImage:[NSNumber numberWithInt:i]];
  64. });
  65. }
  66.  
  67. }
  68.  
  69. - (void)loadImage:(NSNumber *)index {
  70. //如果在串行队列中会发现当前的线程打印完全一样 因为她们在一个线程中
  71. NSLog(@"thread is: %@",[NSThread currentThread]);
  72. int i = (int)[index integerValue];
  73. //请求数据
  74. NSData *data = [self requestData:i];
  75. //回到主线程更新UI
  76. dispatch_sync(dispatch_get_main_queue(), ^{
  77. [self updateImageWithData:data andIndex:i];
  78. });
  79.  
  80. }
  81.  
  82. - (void)updateImageWithData:(NSData *)data andIndex:(int) index{
  83. UIImage *image=[UIImage imageWithData:data];
  84. UIImageView *imageView= _imageViews[index];
  85. imageView.image=image;
  86. }
  87.  
  88. - (NSData *)requestData:(int)index {
  89. NSURL *url=[NSURL URLWithString:_imageNames[index]];
  90. NSData *data=[NSData dataWithContentsOfURL:url];
  91.  
  92. return data;
  93. }

在上面的代码中更新UI还使用了GCD方法的主线程队列dispatch_get_main_queue(),其实这与前面两种主线程更新UI没有本质的区别.

并发队列

并发队列同样是使用dispatch_queue_create()方法创建,只是最后一个参数指定为DISPATCH_QUEUE_CONCURRENT进行创建,但是在实际开发中我们通常不会重新创建一个并发队列而是使用dispatch_get_global_queue()方法取得一个全局的并发队列(当然如果有多个并发队列可以使用前者创建)。下面通过并行队列演示一下多个图片的加载。代码与上面串行队列加载类似,只需要修改照片加载方法如下:

  1. -(void)loadImageWithMultiThread{
  2. int count=ROW_COUNT*COLUMN_COUNT;
  3.  
  4. /*取得全局队列
  5. 第一个参数:线程优先级
  6. 第二个参数:标记参数,目前没有用,一般传入0
  7. */
  8. dispatch_queue_t globalQueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, );
  9. //创建多个线程用于填充图片
  10. for (int i=; i<count; ++i) {
  11. //异步执行队列任务
  12. dispatch_async(globalQueue, ^{
  13. [self loadImage:[NSNumber numberWithInt:i]];
  14. });
  15. }
  16. }

GCD中执行任务有异步执行dispatch_async()和同步执行dispathc_sync()。

在GCD中一个操作是多线程执行还是单线程执行取决于当前队列类型和执行方法。只有队列类型为并列类型并且使用异步调用方法执行时才能在多个线程中执行。

串行队列可以按顺序执行 并列队列的一步方法无法确定执行顺序

UI的更新最好采用同步方法,其他操作才用异步方法

GCD中多线程操作方法不需要使用@autoreleasepool,GCD会管理内存。

其他任务执行方法

1.dispatch_apply()重复执行某个任务,但是注意这个方法没有异步执行(为了不阻塞线程可以使用dispatch_async()包装一下)

2.dispatch_once()单次执行一个任务,此方法中的任务只会执行一次,重复调用也没办法重复执行 常用在单利模式中

3.dispatch_time()延时一定的时间后执行

4.dispatch_barrier_async() 使用此方法创建的任务 首先会查看队列中有没有别的任务要执行,如果有,则会等待已有任务执行完毕再执行;同时在此方法后添加的任务必须等待此方法中任务执行后才能执行。(利用这个方法可以控制执行顺序,例如前面先加载最后一张图片的需求就可以先使用这个方法将最后一张图片加载的操作添加到队列,然后调用dispatch_async()添加其他图片加载任务)

5.dispatch_group_async():实现对任务分组管理,如果一组任务全部完成可以通过dispatch_group_notify()方法获得完成通知(需要定义dispatch_group_t作为分组标识)。

iOS多线程之GCD详解的更多相关文章

  1. iOS多线程之NSThread详解

    在iOS中每个进程启动后都会建立一个主线程(UI线程),这个线程是其他线程的父线程.由于iOS中除了主线程,其他子线程是独立于Cocoa Touch的,所以只有主线程可以更新UI界面.iOS多线程的使 ...

  2. iOS多线程之NSOperation详解

    使用NSOperation和NSOperationQueue进行多线程开发,只要将一个NSOperation(实际开发中需要使用其子类 NSInvocationOperation,NSBlockOpe ...

  3. iOS多线程之GCD小记

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

  4. iOS 多线程之GCD的使用

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

  5. IOS 多线程05-OperationQueue 、GCD详解

      注:本人是翻译过来,并且加上本人的一点见解. 1. 开始 目前在 iOS中有两套先进的同步 API 可供我们使用:操作队列OperationQueue和 GCD .其中 GCD 是基于 C 的底层 ...

  6. iOS-多线程之NSThread详解

    前言 线程是用来执行任务的,线程彻底执行完任务A才能去执行任务B.为了同时执行两个任务,产生了多线程. 我打开一个视频软件,我开辟一个线程A让它执行下载任务,我开辟一个线程B,用来播放视频.我开辟两个 ...

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

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

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

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

  9. iOS 多线程之GCD的简单使用

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

随机推荐

  1. Android NDK环境搭建及调用JNI的简单步骤

    转载请注明:http://www.cnblogs.com/tiantianbyconan/p/3396595.html Java Native Interface (JNI)标准是java平台的一部分 ...

  2. Android View各种尺寸位置相关的方法探究

    Android View各种尺寸位置相关的方法探究 本来想做一个View间的碰撞检测之类的. 动手做了才发现不是想象的那么简单. 首先,写好了碰撞检测的工具类如下: package com.mengd ...

  3. JSON解析实例——使用Json-lib

    JSON解析实例——使用Json-lib Json-lib下载及使用 本文介绍用一个类库进行JSON解析. 工具下载地址:http://sourceforge.net/projects/json-li ...

  4. Java实现---堆排序 Heap Sort

    堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法.学习堆排序前,先讲解下什么是数据结构中的二叉堆. 堆的定义 n个元素的序列{k1,k2,…,kn}当且仅当满足下列关 ...

  5. C语言堆栈入门——堆和栈的区别

    来看一个网上很流行的经典例子: main.cpp int a = 0; 全局初始化区 char *p1; 全局未初始化区 main() { int b; 栈 char s[] = "abc& ...

  6. .Net Attribute详解(上)-Attribute本质以及一个简单示例

    Attribute的直接翻译是属性,这和Property容易产生混淆,所以一般翻译成特性加以区分.Attribute常常的表现形式就是[AttributeName], 随意地添加在class, met ...

  7. iOS开发进阶

    <iOS开发进阶>基本信息作者: 唐巧 出版社:电子工业出版社ISBN:9787121247453上架时间:2014-12-26出版日期:2015 年1月开本:16开页码:268版次:1- ...

  8. ORACLE关于索引是否需要定期重建争论的整理

    ORACLE数据库中的索引到底要不要定期重建呢? 如果不需要定期重建,那么理由是什么? 如果需要定期重建,那么理由又是什么?另外,如果需要定期重建,那么满足那些条件的索引才需要重建呢?关于这个问题,网 ...

  9. 编写Java应用程序。首先,定义描述学生的类——Student,包括学号(int)、 姓名(String)、年龄(int)等属性;二个方法:Student(int stuNo,String name,int age) 用于对对象的初始化,outPut()用于输出学生信息。其次,再定义一个主类—— TestClass,在主类的main方法中创建多个Student类的对象,使用这些对象来测 试Stud

    package zuoye; public class student { int age; String name; int stuNO; void outPut() { System.out.pr ...

  10. 好用的排名函数~ROW_NUMBER(),RANK(),DENSE_RANK() 三兄弟

    排名函数三兄弟,一看名字就知道,都是为了排名而生!但是各自有各自的特色!以下一个例子说明问题!(以下栗子没有使用Partition By 的关键字,整个结果集进行排序) RANK 每个值一个排名,同样 ...