iOS多线程开发之GCD 用法入门

我们知道,在iOS中进行多线程编程,主要有三种方式:【NSThread】、【NSOperation】和【GCD】。其中又以【GCD】为苹果官方最为推荐。本文将利用一个简单的demo,简述GCD的用法入门,以及本人对GCD的一点肤浅理解和学习心得。

先把参考文章列出:

http://www.cnblogs.com/kenshincui/p/3983982.html

http://www.cnblogs.com/sunfrog/p/3305614.html

http://mobile.51cto.com/iphone-446101.htm

http://mobile.51cto.com/iphone-402964.htm

http://mobile.51cto.com/iphone-386596.htm

http://www.cnblogs.com/yangecnu/p/3164167.html

这里重点推荐 http://www.dreamingwish.com/frontui/article/default/the-of-of-of-gcd-tutorial.html GCD系列教程!

关于【NSThread】和【NSOperation】其实在我之前的博文中有所涉及,比如我的这篇博文http://www.cnblogs.com/pigpigDD/p/3975852.html 使用了NSThread方式进行子线程NSTimer计时;以及我的这片博文:http://www.cnblogs.com/pigpigDD/p/3956308.html 使用了NSOperation子类进行网络请求。

下面来说说GCD。

GCD的使用中,最基本也是最核心的概念就是dispatch queue队列。dispatch queue是一个对象,它可以接受任务,并将任务以先到先执行的顺序来执行。dispatch queue可以是并发的或串行的。并发任务会像NSOperationQueue那样基于系统负载来合适地并发进行,串行队列同一时间只执行单一任务。并且,它可以嵌套使用。

1,并行、串行、并行的概念:

并发:在单核心上,多个线程,交替轮换地执行任务命令,每次执行一个任务

串行:在单核心上,一个线程,顺次地执行任务命令,每次执行一个任务

并行:在多核心上,多个线程,同时交替轮换执行任务命令,每次有多个任务同时在多个核心上执行

2,GCD中的三种队列类型

2.1,The main queue: 与主线程功能相同。实际上,提交至main queue的任务会在主线程中执行。main queue可以调用dispatch_get_main_queue()来获得。因为main queue是与主线程相关的,所以这是一个串行队列。

2.2,Global queues: 全局队列是并发队列,并由整个进程共享。进程中存在三个全局队列:高、中(默认)、低三个优先级队列。可以调用dispatch_get_global_queue函数传入优先级来访问队列。

2.3,用户队列: 用户队列 (GCD并不这样称呼这种队列, 但是没有一个特定的名字来形容这种队列,所以我们称其为用户队列) 是用函数 dispatch_queue_create 创建的队列. 这些队列是串行的,可以用来完成同步机制, 有点像传统线程中的mutex。

        2.3.1,dispatch_queue_t queue = dispatch_queue_create("com.dispatch.serial",DISPATCH_QUEUE_SERIAL); 生成一个串行队列,队列中的block按照先进先出(FIFO)的顺序去执行,实际上为单线程执行。第一个参数是队列的名称,在调试程序时会非常有用,所有尽量不要重名了。

        2.3.2,dispatch_queue_t queue = dispatch_queue_create("com.dispatch.concurrent", DISPATCH_QUEUE_CONCURRENT); 生成一个并发执行队列,block被分发到多个线程去执行。

3,分别用串行队列和并发队列演示一个demo

3.1,串行队列加载一系列图片

串行队列,正如前面所说的,就是队列中一系列的任务,按照先进先处理的方式,“排队按序”执行。这里使用了我自己创建了一个串行队列。

 1 //
 2 //  MainView.m
 3 //  GCDDemo
 4 //
 5 //  Created by pigpigdaddy on 14-9-29.
 6 //  Copyright (c) 2014年 pigpigdaddy. All rights reserved.
 7 //
 8
 9 #import "MainView.h"
10
11 #define ROW_COUNT 5
12 #define COLUMN_COUNT 3
13 #define IMAGEVIEW_BASE_TAG 100
14
15 @interface MainView()
16
17 @property (nonatomic, strong)NSMutableArray *dataArray;
18 @property (nonatomic, strong)UIScrollView *scrollView;
19
20 @end
21
22 @implementation MainView
23
24 - (id)initWithFrame:(CGRect)frame
25 {
26     self = [super initWithFrame:frame];
27     if (self) {
28         // Initialization code
29         [self initData];
30         [self initView];
31     }
32     return self;
33 }
34
35 - (void)initData
36 {
37     // 存储图片地址的数组
38     self.dataArray = [[NSMutableArray alloc] init];
39     for (int i = 0; i<ROW_COUNT*COLUMN_COUNT; i++) {
40         [self.dataArray addObject:[NSString stringWithFormat:@"http://images.cnblogs.com/cnblogs_com/pigpigDD/616506/o_%d.png", i+1]];
41     }
42 }
43
44 - (void)initView
45 {
46     // 创建scrollView
47     self.scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
48     [self addSubview:self.scrollView];
49
50     // 创建用于显示的UIImageView
51     for (int i = 0; i<ROW_COUNT; i++) {
52         for (int j = 0; j<COLUMN_COUNT; j++) {
53             UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100*(j%COLUMN_COUNT)+5, 110*(i%ROW_COUNT)+5, 100, 110)];
54             imageView.tag = IMAGEVIEW_BASE_TAG+j+i*3;
55             [self.scrollView addSubview:imageView];
56         }
57     }
58     self.scrollView.contentSize = CGSizeMake(320, 575);
59
60     // 开始加载的按钮
61     UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
62     button.backgroundColor = [UIColor lightGrayColor];
63     button.frame = CGRectMake(100, self.bounds.size.height-50,80, 30);
64     [button setTitle:@"开始加载" forState:UIControlStateNormal];
65     [button addTarget:self action:@selector(loadImage) forControlEvents:UIControlEventTouchUpInside];
66     [self addSubview:button];
67 }
68
69 - (void)downImage:(int)index{
70     // 获取图片
71     NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@", [self.dataArray objectAtIndex:index]]];
72     NSData *data = [NSData dataWithContentsOfURL:url];
73
74     UIImage *image = [UIImage imageWithData:data];
75
76     // 获取主线程队列
77     dispatch_queue_t mainQueue = dispatch_get_main_queue();
78     // 在主线程中更新下载好的图片
79     dispatch_async(mainQueue, ^{
80         UIImageView *imageView = (UIImageView *)[self viewWithTag:IMAGEVIEW_BASE_TAG + index];
81         imageView.image = image;
82     });
83 }
84
85
86 - (void)loadImage
87 {
88     // 创建一个串行队列
89     dispatch_queue_t serialQueue = dispatch_queue_create("com.dispatch.serialQueue", DISPATCH_QUEUE_SERIAL);
90     for (int i = 0; i<ROW_COUNT*COLUMN_COUNT; i++) {
91         dispatch_async(serialQueue, ^{
92             [self downImage:i];
93         });
94     }
95 }
96
97 @end

这里的MainView是我自定义的一个继承自UIView的类,他在window的rootViewController实例中初始化并加载。

效果:

可以看到,当点击“开始加载”按钮后,图片按照设置的顺序依次下载并显示。同时上下滑动scrollView,由于下载图片数据不发生在主线程,所以不会发生卡顿的现象。

3.2,并发队列加载一系列图片

采用并发队列,图片无序下载并显示。这里只需要修改-(void)loadImage函数实现即可:

 1 -(void)loadImage{
 2     int count=ROW_COUNT*COLUMN_COUNT;
 3
 4     // 使用全局并发队列
 5     //dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
 6
 7     // 使用自己创建的并发队列
 8     dispatch_queue_t concurrentQueue = dispatch_queue_create("com.dispatch.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
 9     //创建多个线程用于填充图片
10     for (int i=0; i<count; ++i) {
11         //异步执行队列任务
12         dispatch_async(concurrentQueue, ^{
13             [self downImage:i];
14         });
15     }
16 }

正如2.2和2.3中所写的,并发队列可以使用全局并发队列,也可以使用自己创建的并发队列。

效果如下:

4,注意点:

不论是串行队列还是并发队列,只有在异步调用的时候才是真正启用了多线程,使用同步调用则其实是在主线程上运行!你可以NSLog打出[NSThread currentThread];来分析。

以上对GCD的基本用法,和一些基本概念做了归纳总结。我觉得其实GCD的基本使用是很简单的,但是GCD中有很多细节,和一些进阶的东西,还是值得好好研究学习的。争取在以后的文章中,慢慢归纳总结出来。

时间: 2024-10-06 04:23:57

iOS多线程开发之GCD 用法入门的相关文章

iOS多线程开发之GCD(下篇)

上篇和中篇讲解了什么是GCD,如何使用GCD,这篇文章将讲解使用GCD中将遇到的死锁问题.有兴趣的朋友可以回顾<iOS多线程开发之GCD(上篇)>和<iOS多线程开发之GCD(中篇)>. 言归正传,我们首先来回顾下死锁,所谓死锁: 是指两个或两个以上的进程(线程)在执行过程中,因争夺资源(如数据源,内存等,变量不是资源)而造成的一种互相等待的现象,若无外部处理作用,它们都将无限等待下去. 死锁形成的原因: 系统资源不足 进程(线程)推进的顺序不恰当: 资源分配不当 死锁形成的条件:

IOS多线程开发之GCD

概要 GCD的全称是Grand Central Dispatch(译为中心调度队列?),可以理解为线程管理队列,是苹果公司为多核的并行运算提出的解决方案,能够根据系统环境自适应线程管理,基本属于全自动的线程管理. 在GCD里面,任务需要放到队列里面执行,队列根据自身属性分发任务执行,不过原则总是FIFO.队列分为串行和并行队列,串行队列是队列里面只有一个线程,所以队列里面只有一个任务在执行,而并行则会根据系统环境,自动调节线程数,可支持同时多个任务执行. GCD提供了创建以及获取队列的方法,包括

iOS多线程开发之NSOperation - 快上车,没时间解释了!

一.什么是NSOperation? NSOperation是苹果提供的一套多线程解决方案.实际上NSOperation是基于GCD更高一层的封装,但是比GCD更加的面向对象.代码可读性更高.可控性更强,很屌的是加入了操作依赖. 默认情况下,NSOperation单独使用时只能同步执行操作,并没有开辟新线程的能力,只有配合NSOperationQueue才能实现异步执行.讲到这里,我们不难发现GCD和NSOperation实现的方式很像,其实这更像是废话,NSOperation本身就是基于GCD的

iOS 多线程开发之OperationQueue(二)NSOperation VS GCD

原创Blog,转载请注明出处 blog.csdn.net/hello_hwc 欢迎关注我的iOS SDK详解专栏 http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html 前言:最近有点忙,所以这个月更新的博客数量有些下降,估计这个月和下个月博客更新的数量都在10篇左右.回到正题,本文会比较下GCD和NSOperation两种多线程的实现方式.然后讲解下如何选择,以及简单的示例. 选择GCD or NSOperationQueue

IOS多线程开发之NSThread

概要 使用NSThread的例子,线程创建.启动.线程同步.锁.线程的交互,需要注意的时线程的交互,因为IOS规定只有主线程能够修改UI,所以如果子线程要修改UI的话,需要与主线程交互,即调用方法- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;实现 示例代码 // // ViewController.m // NSThreadDemo // // Crea

多线程开发之GCD

简介GCD本身是苹果公司为多核的并行运算提出的解决方案.GCD在工作时会自动利用更多的处理器核心,以充分利用更强大的机器.GCD是Grand Central Dispatch的简称,它是基于C语言的.如果使用GCD,完全由系统管理线程,我们不需要编写线程代码.只需定义想要执行的任务,然后添加到适当的调度队列(dispatch queue).GCD会负责创建线程和调度你的任务,系统直接提供线程管理 GCD优势 GCD可用于多核的并行运算 GCD会自动利用更多的CPU内核(比如双核.四核) GCD会

iOS开发之Auto Layout入门

随着iPhone6与iOS8的临近,适配的问题讲更加复杂,最近学习了一下Auto Layout的使用,与大家分享.  什么是Auto Layout? Auto Layout是iOS6发布后引入的一个全新的布局特性,其目的是弥补以往Autoresizing在布局方面的不足之处,以及未来面对更多尺寸适配时界面布局可以更好的适应. 为什么要用Auto Layout? Autolayout能解决不同屏幕(iPhone4,iPhone5,iPad...)之间的适配问题. 在iPhone4时代开发者只需要适

iOS游戏开发之UIDynamic

iOS游戏开发之UIDynamic 简介 什么是UIDynamic UIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架 可以认为是一种物理引擎,能模拟和仿真现实生活中的物理现象重力.弹性碰撞等现象 物理引擎的价值 广泛用于游戏开发,经典成功案例是“愤怒的小鸟” 让开发人员可以在远离物理学公式的情况下,实现炫酷的物理仿真效果 提高了游戏开发效率,产生更多优秀好玩的物理仿真游戏 知名的2D物理引擎 Box2d Chipmunk 使用步骤 要想使用UIDynamic来实现物理仿

iOS项目开发之Socket编程

有一段时间没有认真总结和写博客了 前段时间找工作.进入工作阶段.比较少静下来认真总结,现在静下心来总结一下最近的一些心得 前言 AsyncSocket介绍 AsyncSocket详解 AsyncSocket示例 一.前言 公司的项目用到了Socket编程,之前在学习的过程当中,用到的更多的还是http请求的方式.但是既然用到了就必须学习一下,所以就在网上找一些例子,然后想自己写一个demo.可是发现很多写iOS Socket的博客并没有很详细的说明,也可能是大神们觉得其他东西都浅显易懂. 自己专