iOS开发多线程篇—GCD介绍
iOS开发多线程中的GCD介绍
什么是GCD?
GCD-(Grand Central Dispatch)是Apple公司开发的一种技术。这种技术可以在多核硬件中并发处理多个任务。也可以说,GCD是多线程的一种扩展和替代技术。GCD 在Mac OS x 10.6 和 IOS 4.0 以后开始支持.GCD 的核心是分派队列。不论在 iOS 还是 Max OS X 分派队列,正如我们快看到的是 由位于主操作系统的 GCD 来管理的线程池。你不会直接与线程有工作关系。你只在分派队列上工作,将任务分派到这个队列上并要求队列来调用你的任务。GCD 为运行任务提供了几个选择:同步执行、异步执行和延迟执行等。
GCD有什么特点:
1.GCD可以在充分利用多核硬件并发处理多个任务。也就是说,效率高。
2.GCD 的API提供了很多同步,异步,分组等正对多任务,同步,异步的操作。也就是一种比多线程还要牛X
写的技术。
3.使用GCD我们可以更容易的利用多核处理器并行处理任务。
4.GCD 使用后不用程序去管理线程的开闭,GCD会在系统层面上去动态检测系统状态,开闭线程。
什么时候使用多线程?
在实际开发中我们常常把那些比较耗时且与UI无关的操作放到非主线程中去执行,避免这些耗时操作阻塞主线程导致界面操作起来很卡。比如:加载网络数据、本地存储、读取、更新大量数据这些情况都应该使用多线程。
我们可以在global_queue中做一些long-running的任务,完成后在main_queue中更新UI,避免UI阻塞,无法响应用户操作
任务和队列
GCD中有2个核心概念
(1)任务:执行什么操作
(2)队列:用来存放任务
GCD的使用就2个步骤
(1)定制任务
(2)确定想做的事情
将任务添加到队列中,GCD会自动将队列中的任务取出,放到对应的线程中执行
提示:任务的取出遵循队列的FIFO原则:先进先出,后进后出
执行任务
1.GCD中有2个用来执行任务的函数
说明:把右边的参数(任务)提交给左边的参数(队列)进行执行。
(1)用同步的方式执行任务 dispatch_sync(dispatch_queue_t queue, dispatch_block_tblock);
参数说明:
queue:队列
block:任务
(2)用异步的方式执行任务 dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
2.同步和异步的区别
同步:在当前线程中执行
异步:在另一条线程中执行
队列
1.队列的类型
GCD的队列可以分为2大类型
(1)并发队列(ConcurrentDispatch Queue)
可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)并发功能只有在异步(dispatch_async)函数下才有效
(2)串行队列(SerialDispatch Queue)
让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
2.补充说明
有4个术语比较容易混淆:同步、异步、并发、串行
同步和异步决定了要不要开启新的线程
同步:在当前线程中执行任务,不具备开启新线程的能力
异步:在新的线程中执行任务,具备开启新线程的能力
并发和串行决定了任务的执行方式
并发:多个任务并发(同时)执行
串行:一个任务执行完毕后,再执行下一个任务
3.串行队列
GCD中获得串行有2种途径
(1)使用dispatch_queue_create函数创建串行队列
dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr); // 队列名称, 队列属性,一般用NULL即可
示例:
dispatch_queue_t queue =dispatch_queue_create("wendingding", NULL); // 创建
dispatch_release(queue); // 非ARC需要释放手动创建的队列
(2)使用主队列(跟主线程相关联的队列)
主队列是GCD自带的一种特殊的串行队列,放在主队列中的任务,都会放到主线程中执行
使用dispatch_get_main_queue()获得主队列
示例:
dispatch_queue_t queue =dispatch_get_main_queue();
4.并发队列
GCD默认已经提供了全局的并发队列,供整个应用使用,不需要手动创建
使用dispatch_get_global_queue函数获得全局的并发队列
dispatch_queue_tdispatch_get_global_queue(dispatch_queue_priority_t priority,unsigned longflags); // 此参数暂时无用,用0即可
示例:
这个参数是留给以后用的,暂时用不上,传个0。
第一个参数为优先级,这里选择默认的。获取一个全局的默认优先级的并发队列。
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 获得全局并发队列
说明:全局并发队列的优先级
#define DISPATCH_QUEUE_PRIORITY_HIGH 2// 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT0 // 默认(中)
#define DISPATCH_QUEUE_PRIORITY_LOW(-2) // 低
#defineDISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台
5.各种队列的执行效果
GCD的函数介绍
执行某个代码片段N次。
dispatch_apply(5, globalQ, ^(size_t index) { // 执行5次 });
2. dispatch_once
// dispatch_once这个函数,它可以保证整个应用程序生命周期中某段代码只被执行一次! static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ //代码被执行一次 });
3.dispatch_after
推迟一段时间之后,执行代码片段
//有时候我们需要等个几秒钟然后做个动画或者给个提示,这时候可以用dispatch_after这个函数: double delayInSeconds = 2.0; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ // code to be executed on the main queue after delay });
让后台2个线程并行执行,然后等2个线程都结束后,再汇总执行结果。这个可以用dispatch_group, dispatch_group_async 和dispatch_group_notify来实现,示例如下:
dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{ // 并行执行的线程一 }); dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{ // 并行执行的线程二 }); dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{ // 汇总结果 });
下面是dispatch_group的使用示范
-(void) groupUSE{ dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:1]; NSLog(@"第一个任务"); }); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:2]; NSLog(@"第二个任务"); }); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:3]; NSLog(@"第三个任务"); }); dispatch_group_notify(group, queue, ^{ NSLog(@"汇总任务"); }); }
代码示范
(1)用异步函数往并发队列中添加任务
// // YYViewController.m // 08-GCD基本使用 // // Created by apple on 14-6-24. // Copyright (c) 2014年 itcase. All rights reserved. // #import "YYViewController.h" @interface YYViewController () @end @implementation YYViewController - (void)viewDidLoad { [super viewDidLoad]; //1.获得全局的并发队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //2.添加任务到队列中,就可以执行任务 //异步函数:具备开启新线程的能力 dispatch_async(queue, ^{ NSLog(@"下载图片1----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"下载图片2----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"下载图片2----%@",[NSThread currentThread]); }); //打印主线程 NSLog(@"主线程----%@",[NSThread mainThread]); } @end
(2)用异步函数往串行队列中添加任务
// // YYViewController.m // 09—GCD基本使用2 // // Created by apple on 14-6-24. // Copyright (c) 2014年 itcase. All rights reserved. // #import "YYViewController.h" @interface YYViewController () @end @implementation YYViewController - (void)viewDidLoad { [super viewDidLoad]; //打印主线程 NSLog(@"主线程----%@",[NSThread mainThread]); //创建串行队列 dispatch_queue_t queue= dispatch_queue_create("wendingding", NULL); //第一个参数为串行队列的名称,是c语言的字符串 //第二个参数为队列的属性,一般来说串行队列不需要赋值任何属性,所以通常传空值(NULL) //2.添加任务到队列中执行 dispatch_async(queue, ^{ NSLog(@"下载图片1----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"下载图片2----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"下载图片2----%@",[NSThread currentThread]); }); //3.释放资源 // dispatch_release(queue); } @end
(3)用同步函数往并发队列中添加任务
// // YYViewController.m // 10-CGD基本使用3 // // Created by apple on 14-6-24. // Copyright (c) 2014年 itcase. All rights reserved. // #import "YYViewController.h" @interface YYViewController () @end @implementation YYViewController /** * 用同步函数往并发队列中添加任务 */ - (void)viewDidLoad { [super viewDidLoad]; //打印主线程 NSLog(@"主线程----%@",[NSThread mainThread]); //创建串行队列 dispatch_queue_t queue= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //2.添加任务到队列中执行 dispatch_sync(queue, ^{ NSLog(@"下载图片1----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"下载图片2----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"下载图片3----%@",[NSThread currentThread]); }); } @end
(4)用同步函数往串行队列中添加任务
// // YYViewController.m // 11—CGD基本使用4 // // Created by apple on 14-6-24. // Copyright (c) 2014年 itcase. All rights reserved. // #import "YYViewController.h" @interface YYViewController () @end @implementation YYViewController /** *用同步函数往串行队列中添加任务 */ - (void)viewDidLoad { [super viewDidLoad]; NSLog(@"用同步函数往串行队列中添加任务"); //打印主线程 NSLog(@"主线程----%@",[NSThread mainThread]); //创建串行队列 dispatch_queue_t queue= dispatch_queue_create("wendingding", NULL); //2.添加任务到队列中执行 dispatch_sync(queue, ^{ NSLog(@"下载图片1----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"下载图片2----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"下载图片3----%@",[NSThread currentThread]); }); } @end