学习iOS到今天有3个月,也要准备面试,总是碰到gcd的问题,今天翻看了一下gcd的资料,整理一下。如果您是大牛,看到笑完之后请赐教,菜鸟一起学习。
(1)GCD是什么
Grand Central Dispatch(宏伟的派件中心 直译个人叫法,非官方):系统管理线程,你不需要编写线程代码。只需要定义想要执行的任务然后添加到适当的dispath queue.GCD会负责创建线程和调度你的任务。系统直接提供线程管理,比应用实现更加高效。
(2)GCD dispatch queues(派遣队列-个人叫法) 是执行任务的强大工具,允许你同步或异步地执行任意代码block。原先使用单独线程执行的所有任务都可以替换为使用dispatch quues。而dispatch queues最大的优点在于使用简单而且更加高效。
dispatch queue 是类似于对象的结构体,管理你提交给它的任务,而且都是先进先出(FIFO)的数据结构。因此queue中的任务总是以添加的顺序开始执行。GCD提供了几种dispatch queues 。不过你也自己创建。
三种queues:
串行Dispatch Queue:(待补充说明)
全局并发Dispatch Queue:(待补充说明)
main dispatch queue;(待补充说明)
(3)GCD 和线程相比的优点?
应用使用dispatch queue,相比线程有很多优点,最直接的优点是简单,不用编写线程创建和管理的代码,让你集中精力编写实际工作的代码。另外系统管理线程更加高效,并且可以动态调控所有线程。
dispatch queues 比线程具有更强的可预测性,例如两个线程访问共享资源,你可能无法控制哪个线程先后访问;但是把两个任务添加到串行queue,则可以确保两个任务对共享资源的饿访问顺序。同时基于queue的同步也比基于锁的线程同步机制更加高效。
(4)如何获得三种队列?
获得全局并发Dispatch Queue:
系统给每个应用提供三个并发dispatch queue ,所有应用全局共享,三个queue的区别是优先级。你不需要显示的创建这些queue,使用dispatch_get_global_queue 函数来获取这三个queue,代码
dispatch_queue_t firstGloabel = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
第一个参数是优先级别,级别不同队列是不一样的,第二个参数flag作为保留字段备用(一般为0)
创建串行Dispatch Queue :
应用的任务需要按需要按特定顺序执行时,就需要使用串行Dispatch Queue ,串行queue每次只能执行一个任务。你可以使用串行queue来替代锁,保护共享资源或可变的数据结构。
dispatch_queue_t firstQueue = dispatch_queue_create("com.example.Haisheng", NULL);
dispatch_queue_create函数创建串行queue,两个参数分别是queue名和一组queue属性。获得主队列:
dispatch_queue_t mainQueue = dispatch_get_main_queue();
(5)添加任务到Queue
要执行一个任务,你需要将它dispatch到一个适当的dispatch queue,你可以同步或异步地dispatch一个任务,也可以单个或按组来dispatch 。一旦进入到queue,queue会负责尽快地执行你的任务。
你可以异步或同步地添加一个任务到Queue,金可能地使用dispatch_async或dispatch_async_f函数异步地dispatch任务。
来点实际的
// GCD 相关函数说明
// dispatch_get_main_queue();
// dispatch_async 函数会将传入的block块放入指定的queue里运行。这个函数是异步的,这就意味着它会立即返回而不管block是否运行结束。因此,我们可以在block里运行各种耗时的操作(如网络请求)而同时不会阻塞UI线程。
// dispatch_get_global_queue 会获取一个全局队列,我们姑且理解为系统为我们开启的一些全局线程。我们用priority指定队列的优先级,而flag作为保留字段备用(一般为0)。
// dispatch_get_main_queue 会返回主队列,也就是UI队列。它一般用于在其它队列中异步完成了一些工作后,需要在UI队列中更新界面(比如上面代码中的[self updateUIWithResult:result])的情况。
最后上一个磊哥的例子:
<span style="font-size:14px;">//
// RootViewController.m
// GCD
//
// Created by on 14-9-1.
// Copyright (c) 2014年 . All rights reserved.
//
#import "RootViewController.h"
@interface RootViewController ()
@end
@implementation RootViewController
#define kImageString @"http://static.oschina.net/uploads/user/136/272738_50.jpg?t=1409534522000"
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setTitle:@"gcd" forState:UIControlStateNormal];
[btn setFrame:CGRectMake(10,30,300,50)];
[btn addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
/*1、GCD 是苹果iOS4.0之后和block一起出现的技术,是苹果封装的更底层(c)更高效的多线程处理技术
*2、GCD (grand-central-dispatch)是目前使用的最普遍的多线程处理技术,因为高效、简洁、实用
*/
- (void)btnClicked:(UIButton *)btn{
//gcd 中有一个主队列来管理和调度主线程
//有三个优先级的全局队列用于管理和调度子线程
//通过优先级为default的全局队列,在主线程之外,开辟的一个子线程
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//此block 为子线程对应的函数
NSURL *url = [NSURL URLWithString:kImageString];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
if (image) {
//回到主线程,执行后续的操作
//通过主队列回到主线程
dispatch_async(dispatch_get_main_queue(), ^{
//此block中的代码 在主线程中执行
self.view.backgroundColor = [UIColor colorWithPatternImage:image];
});
}
});
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
</span>