GCD与多线程
GCD与多线程
GCD,全称Grand Central Dispath,是苹果开发的一种支持并行操作的机制。它的主要部件是一个FIFO队列和一个线程池,前者用来添加任务,后者用来执行任务。
GCD中的FIFO队列称为dispatch queue,它可以保证先进来的任务先得到执行(但不保证一定先执行结束)。
通过与线程池的配合,dispatch queue分为下面两种:
- Serial Dispatch Queue -- 线程池只提供一个线程用来执行任务,所以后一个任务必须等到前一个任务执行结束才能开始。
- Concurrent Dispatch Queue -- 线程池提供多个线程来执行任务,所以可以按序启动多个任务并发执行。
1. Basic Management
我们可以通过dispatch_queue_cretae来创建队列,然后用dispatch_release释放。比如下面两段代码分别创建串行队列和并行队列:
- dispatch_queue_t serialQ = dispatch_queue_create("eg.gcd.SerialQueue", DISPATCH_QUEUE_SERIAL);
- dispatch_async(serialQ, ^{
- // Code here
- });
- dispatch_release(serialQ);
- dispatch_queue_t concurrentQ = dispatch_queue_create("eg.gcd.ConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
- dispatch_async(concurrentQ, ^{
- // Code here
- });
- dispatch_release(concurrentQ);
而系统默认就有一个串行队列main_queue和并行队列global_queue:
- dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_queue_t mainQ = dispatch_get_main_queue();
通常,我们可以在global_queue中做一些long-running的任务,完成后在main_queue中更新UI,避免UI阻塞,无法响应用户操作:
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- // long-running task
- dispatch_async(dispatch_get_main_queue(), ^{
- // update UI
- });
- });
上面提到dispatch_async这个接口,用来提交blcok给指定queue进行异步执行。这个接口会在成功提交block后立即返回,然后继续执行下去。由于block是定义在栈上的,所以需要将其复制到堆上,见这里。
与之相对应的是dispatch_sync接口,提交block以供同步执行。这个接口会等到block执行结束才返回,所以不需要复制block。So,如果在调用该接口在当前queue上指派任务,就会导致deadlock。维基百科上给了段示例代码:
- dispatch_queue_t exampleQueue = dispatch_queue_create("com.example.unique.identifier", NULL );
- dispatch_sync( exampleQueue,^{
- dispatch_sync( exampleQueue,^{
- printf("I am now deadlocked...\n");
- });});
- dispatch_release( exampleQueue );
如果追求的是并发,那么dispatch_sync有什么用呢?关于dispatch_sync的用途,StackOverFlow是这样讨论的:
Can anyone explain with really clear use cases what the purpose of
dispatch_syncinGCDis for? I can't understand where and why I would have to use this.高手回答:
You use it when you want to execute a block and wait for the results.
One example of this is the pattern where you're using a dispatch queue instead of locks for synchronization. For example, assume you have a shared NSMutableArray
a, with access mediated by dispatch queueq. A background thread might be appending to the array (async), while your foreground thread is pulling the first item off (synchronously):NSMutableArray*a =[[NSMutableArray alloc] init];// All access to `a` is via this dispatch queue!dispatch_queue_t q = dispatch_queue_create("com.foo.samplequeue", NULL); dispatch_async(q,^{[a addObject:something];});// append to array, non-blocking __block Something*first = nil;// "__block" to make results from block available
dispatch_sync(q,^{// note that these 3 statements...if([a count]>0){// ...are all executed together...
first =[a objectAtIndex:0];// ...as part of a single block...[a removeObjectAtIndex:0];// ...to ensure consistent results}});下面附上一个Demo :(后台队列下载图片,当下载完后,调用主线程在前台显示)
在Concoller中:
- -(void)viewDidAppear:(BOOL)animated{
- dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_async(concurrentQueue, ^{
- __block UIImage *image = nil;
- dispatch_sync(concurrentQueue, ^{
- /* 下载图片 */
- NSString *urlAsString = @"http://images.apple.com/mac/home/images/promo_lead_macbook_air.jpg";
- NSURL *url = [NSURL URLWithString:urlAsString];
- NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
- NSError *downloadError = nil;
- NSData *imageData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&downloadError];
- if (downloadError == nil && imageData != nil){
- image = [UIImage imageWithData:imageData];
- } else if(downloadError!=nil){
- NSLog(@"Error happened = %@", downloadError);
- }else {
- NSLog(@"No data could get downloaded from the URL.");
- }
- });
- //在主队列中把图片展示给用户
- dispatch_sync(dispatch_get_main_queue(), ^{
- if (image != nil){
- /* 创建一个UIImageView */
- UIImageView *imageView = [[UIImageView alloc]
- initWithFrame:self.view.bounds];
- /* 设置图片*/
- [imageView setImage:image];
- /* 设置图片比例*/
- [imageView setContentMode:UIViewContentModeScaleAspectFit];
- /* 添加视图 */
- [self.view addSubview:imageView];
- } else {
- NSLog(@"Image isn't downloaded. Nothing to display.");
- } });
- });
- }
运行结果:
GCD与多线程的更多相关文章
- iOS-----使用GCD实现多线程
使用GCD实现多线程 GCD的两个核心概念如下: 队列 队列负责管理开发者提交的任务,GCD队列始终以FIFO(先进先出)的方式来处理任务---但 由于任务的执行时间并不相同,因此先处理的任务并一定先 ...
- apple平台下的objc的GCD,多线程编程就是优雅自然。
在apple的操作系统平台里,GCD使得多线程编程是那么的优雅自然.在传统的多线程编程中,首先要写线程处理循环:之后还有事件队列,消息队列:还要在线程循环中分离事件解释消息,分派处理:还要考虑线程间是 ...
- GCD的多线程实现方式,线程和定时器混合使用
GCD (Grand Central Dispatch) 性能更好,追求性能的话 1.创建一个队列 //GCD的使用 //创建一个队列 dispatch_queue_t queue = dispatc ...
- iOS开发中GCD在多线程方面的理解
GCD为Grand Central Dispatch的缩写. Grand Central Dispatch (GCD)是Apple开发的一个多核编程的较新的解决方法.在Mac OS X 10.6雪豹中 ...
- [转]关于GCD与多线程
GCD是什么,你知道吗?你知道了GCD,你确定你会使用吗? 这一篇文章是站在初学者角度去分析GCD,原因是这个很多iOS开发者根本就没用过,即使用过,不知道其中的原理.讲解之前认识一下什么是线程,为什 ...
- GCD网络多线程---同步运行,异步运行,串行队列,并行队列
总结:同步(无论是串行还是并行)----不又一次开辟子线程 异步(无论是串行还是并行)----开辟子线程 GCD: dispatch queue 主线程的main queue 并行队列 global ...
- GCD死锁 多线程
NSLog("); dispatch_sync(dispatch_get_main_queue(), ^{ // sync同步 main串行 // 同步,异步--线程 同步-主线程 // m ...
- IOS学习之路八(GCD与多线程)
GCD,全称Grand Central Dispath,是苹果开发的一种支持并行操作的机制.它的主要部件是一个FIFO队列和一个线程池,前者用来添加任务,后者用来执行任务. GCD中的FIFO队列称为 ...
- GCD实现多线程 实践
GCD中弹窗的正确写法 - (void)viewDidLoad { //…… if (![self isStartLoading]) [self startLoading:nil]; //loadin ...
随机推荐
- Swift中文手册 -- The Basics
原文:Swift中文手册 -- The Basics 基础部分 Swift 是 iOS 和 OS X 应用开发的一门新语言.然而,如果你有 C 或者 Objective-C 开发经验的话,你会发现 S ...
- HDU 3523 Image copy detection(KM最大匹配)
HDU 3523 Image copy detection 题目链接 题意:这题事实上题意读懂就简单了,说白了就是1-n放到1-n列,每列的值为每列上数字和该数字的差的绝对值,然后求总和最小 思路:就 ...
- WebService它CXF注释错误(两)
WebService它CXF注解 1.详细报错例如以下 五月 04, 2014 11:24:12 下午 org.apache.cxf.wsdl.service.factory.ReflectionSe ...
- Webbrowser控件史上最强技巧全集
原文:Webbrowser控件史上最强技巧全集 Webbrowser控件史上最强技巧全集 VB调用webbrowser技巧集 1.获得浏览器信息: Private Sub Command1_Click ...
- Windows Phone 8.1 多媒体(1):相片
原文:Windows Phone 8.1 多媒体(1):相片 Windows Phone 8.1 多媒体(1):相片 Windows Phone 8.1 多媒体(2):视频 Windows Phone ...
- 【转】height,posHeight和pixelHeight区别
height 返回高度 带单位 posHeight 不带单位的数字 pixelHeight 转换成像素后的数字 不带单位 更多资料 http://www.1fan.com.cn
- c#-Artificial Intelligence Class
NET Artificial Intelligence Class http://www.codeproject.com/KB/recipes/aforge_neuro/neuro_src.zip
- 2014阿里实习生面试题——mysql如何实现的索引
这是2014北京站的两副面孔阿里实习生问题扯在一起: 在MySQL中.索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,比方MyISAM和InnoDB存储引擎. MyISAM索引实现: ...
- asp.net中TextBox里面实现回车触发指定事件
原文:asp.net中TextBox里面实现回车触发指定事件 我在一个user_top用户控件里面做了个包括搜索的功能.然后再一个页面中添加这个用户控件.浏览时候在textbox里面输入搜索内容后.下 ...
- Light OJ 1316 A Wedding Party 最短路+状态压缩DP
题目来源:Light OJ 1316 1316 - A Wedding Party 题意:和HDU 4284 差点儿相同 有一些商店 从起点到终点在走过尽量多商店的情况下求最短路 思路:首先预处理每两 ...