iOS开发-多线程之GCD(Grand Central Dispatch)
Grand Central Dispatch(GCD)是一个强有力的方式取执行多线程任务,不管你在回调的时候是异步或者同步的,可以优化应用程序支持多核心处理器和其他的对称多处理系统的系统。开发使用的过程中只需要将执行的任务并添加到到适当的Dispatch Queue中,GCD就能生成必要的线程并计划执行任务。Dispatch Queue更简单而且在实现符合需求的多线程任务时更有效率。Dispatch Queue一般来说有三种方式,如下图:
Serial执行的时候的先进先出,Concurrent是并发执行任务,main属于全局可用的quene;从定义上看我们可以知道Serial放在一个队列里面,占用一个线程,ConCurrent则占用多个线程,具体数量由系统决定,执行的顺序是随机的。
Dispatch Quene简单调用:
//调用队列的两种不同的方式
dispatch_queue_t quene = dispatch_queue_create("http://www.cnblogs.com/xiaofeixiang", NULL);
//异步调用执行
dispatch_async(quene, ^{
NSLog(@"dispatch_async简单调用-FlyElephant");
});
//同步
dispatch_sync(quene, ^{
NSLog(@"同步执行-FlyElephant");
});
获取全局的队列和主队列的方式,一般更新UI的时候会使用到Main Dispatch Queue,全局的队列比较实际操作中比较常用:
//获取Main Queue
dispatch_queue_t mainQueue =dispatch_get_main_queue();
//获取全局的 Global Queue
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_sync(globalQueue, ^{
NSLog(@"dispatch_get_global_queue调用-FlyElephant");
});
Main使用的时候需要注意的使用异步方式,不然页面会卡死,Main和Global是全局对象,不需要释放,系统会自动处理;
dispatch_queue_t mainQueue =dispatch_get_main_queue(); dispatch_async(mainQueue, ^{
NSLog(@"dispatch_get_main_queue调用-FlyElephant");
self.myImageView.image=[UIImage imageNamed:[NSString stringWithFormat:@"Thread2.jpg"]];
});
延时执行任务dispatch_after,dispatch_after的确切的表示应该是在一定的时间后把任务添加进队列中,如果对时间精度有要求,需要自己根据需求改改:
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,10);
dispatch_after(time, globalQueue,^{
NSLog(@"延迟执行");
});
dispatch_apply其用法就像for的用法,可以指定的block执行指定的次数。如果要对某个数组中的所有元素执行同样的block的时候,这个函数就显得很有用了,用法很简单,指定执行的次数以及Dispatch Queue,在block回调中会带一个索引,然后就可以根据这个索引来判断当前是对哪个元素进行操作,
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_apply(36, globalQueue, ^(size_t i) {
NSLog(@"%zu",i);
});
控制看结果会发现结果是:
2015-02-11 22:54:29.602 ThreadDemo[1404:54736] 2
2015-02-11 22:54:29.602 ThreadDemo[1404:54734] 3
2015-02-11 22:54:29.602 ThreadDemo[1404:54707] 0
2015-02-11 22:54:29.603 ThreadDemo[1404:54736] 4
2015-02-11 22:54:29.603 ThreadDemo[1404:54734] 5
2015-02-11 22:54:29.603 ThreadDemo[1404:54707] 6
2015-02-11 22:54:29.603 ThreadDemo[1404:54736] 7
2015-02-11 22:54:29.603 ThreadDemo[1404:54707] 9
2015-02-11 22:54:29.603 ThreadDemo[1404:54734] 8
2015-02-11 22:54:29.602 ThreadDemo[1404:54733] 1
2015-02-11 22:54:29.603 ThreadDemo[1404:54707] dispatch_apply执行后
Global是并发队列(Concurrent Dispatch Queue),不能保证执行的先后顺序,但dispatch_apply函数是同步的,执行过程中会使线程在此处停住,我们可以在一个异步线程里使用dispatch_apply函数,稍微改改:
dispatch_async(globalQueue, ^{
dispatch_apply(10, globalQueue, ^(size_t i) {
NSLog(@"%zu",i);
});
});
NSLog(@"dispatch_apply执行后");
修改之后的执行结果:
2015-02-11 22:58:24.321 ThreadDemo[1433:56214] dispatch_apply执行后
2015-02-11 22:58:24.321 ThreadDemo[1433:56285] 3
2015-02-11 22:58:24.321 ThreadDemo[1433:56282] 2
2015-02-11 22:58:24.323 ThreadDemo[1433:56285] 4
2015-02-11 22:58:24.321 ThreadDemo[1433:56284] 0
2015-02-11 22:58:24.323 ThreadDemo[1433:56282] 5
2015-02-11 22:58:24.321 ThreadDemo[1433:56283] 1
2015-02-11 22:58:24.323 ThreadDemo[1433:56285] 6
2015-02-11 22:58:24.323 ThreadDemo[1433:56284] 7
2015-02-11 22:58:24.323 ThreadDemo[1433:56282] 8
2015-02-11 22:58:24.323 ThreadDemo[1433:56283] 9
Dispatch Queue暂停与恢复,这个基本没什么说的,就一方法的调用:
//暂停
dispatch_suspend(globalQueue);
//恢复
dispatch_resume(globalQueue);
dispatch_barrier_async:前面的任务执行结束后才执行,而且之后的任务等它执行完成之后才能执行,具体参考代码:
dispatch_queue_t queue = dispatch_queue_create("http://www.cnblogs.com/xiaofeixiang", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"dispatch_async-keso");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"dispatch_async-FlyElephant");
});
dispatch_barrier_async(queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"dispatch_barrier_async-博客园");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:4];
NSLog(@"dispatch_async-敏捷大拇指");
});
最终执行结果如下,注意观察时间:
2015-02-11 23:08:40.668 ThreadDemo[1475:59699] dispatch_async-keso
2015-02-11 23:08:41.664 ThreadDemo[1475:59698] dispatch_async-FlyElephant
2015-02-11 23:08:44.670 ThreadDemo[1475:59698] dispatch_barrier_async-博客园
2015-02-11 23:08:48.675 ThreadDemo[1475:59698] dispatch_async-敏捷大拇指
dispatch_group:Queue中dispatch_group_wait会等待之前的任务,如果之前的任务比较耗时的话,那么线程阻塞,使用需要谨慎,另外wait的时候可以指定时间的,例子中DISPATCH_TIME_FOREVER表示永远等待,如果是在OS X 10.8或iOS 6以及之后版本中使用,Dispatch Group将会由ARC自动管理,如果是在此之前的版本,需要自己手动释放。
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, ^{
NSLog(@"Group任务One");
}); dispatch_group_async(group, queue, ^{
NSLog(@"Group任务Two");
}); dispatch_group_wait(group, DISPATCH_TIME_FOREVER); NSLog(@"Group任务已经完成");
dispatch_semaphore可以简单理解成信号量,先创建一个信号量,然后等待回调执行任务,执行任务之后要释放,主要的处理点在wait等待上面,简单的代码如下:
dispatch_semaphore_t fd_sema = dispatch_semaphore_create(getdtablesize() / 2);
//等待
dispatch_semaphore_wait(fd_sema, DISPATCH_TIME_FOREVER); NSLog(@"dispatch_semaphore测试");
//释放
dispatch_semaphore_signal(fd_sema);
dispatch_group(补充)
dispatch_group是一组可以执行的任务,可以设置等待时间,wait等待之前的任务完成,同样还存在另外一个通知功能,一组任务完成之后通知其他任务执行,参考代码如下:
dispatch_queue_t myQueue=dispatch_queue_create("FlyElephant", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t myGroup=dispatch_group_create();
dispatch_group_async(myGroup, myQueue, ^{
NSLog(@"dispatch_group_async执行---博客园");
}); dispatch_group_async(myGroup, myQueue, ^{
NSLog(@"dispatch_group_async执行---FlyElephant");
}); dispatch_group_async(myGroup,myQueue, ^{
NSLog(@"dispatch_group_async执行---http://www.cnblogs.com/xiaofeixiang/");
});
//表示永远等待之前的状态
dispatch_group_wait(myGroup, DISPATCH_TIME_FOREVER);
NSLog(@"Group任务已经完成");
dispatch_group_notify(myGroup, dispatch_get_main_queue(), ^{
[self.label setText:@"Group"];
});
dispathc_semaphore(补充)
关于信号量基本的操作上文中提到了,创建,信号量加+1,信号量-1,信号量小于等于0的时候不执行操作,先看代码:
dispatch_queue_t myQueue=dispatch_queue_create("FlyElephant", DISPATCH_QUEUE_CONCURRENT);
dispatch_semaphore_t semaphore=dispatch_semaphore_create(1);
for (NSInteger i=0; i<20; i++) {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(myQueue, ^{
NSLog(@"currentValue:%ld",i);
dispatch_semaphore_signal(semaphore);
});
}
其中这里是从0到19都是正常的顺序,注意信号量创建的时候我们设置的参数是1,其中如果我们注释,dispatch_semaphore_signal方法,我们会发现代码只会执行一次~
iOS开发-多线程之GCD(Grand Central Dispatch)的更多相关文章
- iOS开发多线程之GCD
Grand Central Dispatch(GCD)是异步执行任务的技术之一.一般将应用程序中记述的线程管理用的代码在系统级中实现.开发者只需要定义想执行的任务并追加到适当的Dispatch Que ...
- GCD (Grand Central Dispatch) 笔记
GCD (Grand Central Dispatch) 是Apple公司开发的一种技术,它旨在优化多核环境中的并发操作并取代传统多线程的编程模式. 在Mac OS X 10.6和IOS 4.0之后开 ...
- iOS开发多线程之NSThread
一.NSThread的属性与方法 1.NSThread 类方法 类方法,顾名思义通过类名直接调用的方法 1. + (void)detachNewThreadWithBlock:(void (^)(vo ...
- iOS开发多线程之NSOperation
NSInvocationOperation The NSInvocationOperationclass is a concrete subclass of NSOperationthat you u ...
- ios理解 -- Pro Mutlithreading and Memory Management for iOS and OS X with ARC, Grand Central Dispatch, and Blocks
Capturing automatic variables Next, you need to learn what the “together with automatic (local) vari ...
- iOS多线程之GCD详解
GCD(Grand Central Dispatch)是基于C语言开发的一套多线程开发机制.也是目前苹果官方推荐的多线程开发方法.iOS三种多线程开发中GCD是抽象层次最高的.当然用起来也是最简单的. ...
- IOS中的多线程之GCD
在ios中,使用多线程有三种方式,分别是:NSThread.NSOperation和NSOperationQueue.GCD,在本节,主要讲解一下CDD的使用. GCD(Grand Central D ...
- (五十五)iOS多线程之GCD
GCD的全称为Grand Central Dispatch,翻译为大中央调度,是Apple开发的一个多线程编程解决方法. 进程和线程的概念: 正在进行中的程序被称为进程,负责程序运行的内存分配,每一个 ...
- [转] iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用
介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其他的对称多处理系统的系统.这建立在任务并行执行的线程池模式的基础上的.它首 ...
随机推荐
- python脚本获取本机公网ip
1.获取公网IP地址方式,访问:http://txt.go.sohu.com/ip/soip 2.python脚本实现: #!/usr/bin/python # -*- coding:utf8 -*- ...
- 洛谷P1527 [国家集训队] 矩阵乘法 [整体二分,二维树状数组]
题目传送门 矩阵乘法 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入格式: 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共N* ...
- Python并发编程系列之多进程(multiprocessing)
1 引言 本篇博文主要对Python中并发编程中的多进程相关内容展开详细介绍,Python进程主要在multiprocessing模块中,本博文以multiprocessing种Process类为中心 ...
- 说一说Servlet的生命周期
servlet有良好的生存期的定义,包括加载和实例化.初始化.处理请求以及服务结束.这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达. Se ...
- dSploitzANTI渗透教程之启动zANTI工具
dSploitzANTI渗透教程之启动zANTI工具 启动zANTI工具 [示例1-2]下面将介绍启动zANTI工具的方法.具体操作步骤如下所示: (1)在Android设备的应用程序界面,选择并启动 ...
- python 全排列
itertools模块现成的全排列: for i in itertools.permutations('abcd',4): print ''.join(i) 相关全排列算法: def perm(l): ...
- CF1042C Array Product 分类讨论+贪心
考虑有无负数(负数的个数为奇视作“有”,否则为“无”)和有无零 无负数无零,全部合并即可 无负数有零,那么把零合并起来,删掉零 有负数无零,把最大的负数找出来,删掉,合并剩余的数 有负数有零,把零和最 ...
- 撩课-Java每天5道面试题第11天
86.如何获得高效的数据库逻辑结构? 从关系数据库的表中 删除冗余信息的过程 称为数据规范化, 是得到高效的关系型数据库表的逻辑结构 最好和最容易的方法. 规范化数据时应执行以下操作: 1.将数据库的 ...
- Codeforces Round #288 (Div. 2) B. Anton and currency you all know 贪心
B. Anton and currency you all know time limit per test 0.5 seconds memory limit per test 256 megabyt ...
- Codeforces Round #287 (Div. 2) C. Guess Your Way Out! 水题
C. Guess Your Way Out! time limit per test 1 second memory limit per test 256 megabytes input standa ...