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释放。比如下面两段代码分别创建串行队列和并行队列:

      1. dispatch_queue_t serialQ = dispatch_queue_create("eg.gcd.SerialQueue", DISPATCH_QUEUE_SERIAL);
      2. dispatch_async(serialQ, ^{
      3. // Code here
      4. });
      5. dispatch_release(serialQ);
      6. dispatch_queue_t concurrentQ = dispatch_queue_create("eg.gcd.ConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
      7. dispatch_async(concurrentQ, ^{
      8. // Code here
      9. });
      10. dispatch_release(concurrentQ);

      而系统默认就有一个串行队列main_queue和并行队列global_queue:

      1. dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      2. dispatch_queue_t mainQ = dispatch_get_main_queue();

      通常,我们可以在global_queue中做一些long-running的任务,完成后在main_queue中更新UI,避免UI阻塞,无法响应用户操作:

      1. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      2. // long-running task
      3. dispatch_async(dispatch_get_main_queue(), ^{
      4. // update UI
      5. });
      6. });

      上面提到dispatch_async这个接口,用来提交blcok给指定queue进行异步执行。这个接口会在成功提交block后立即返回,然后继续执行下去。由于block是定义在栈上的,所以需要将其复制到堆上,见这里

      与之相对应的是dispatch_sync接口,提交block以供同步执行。这个接口会等到block执行结束才返回,所以不需要复制block。So,如果在调用该接口在当前queue上指派任务,就会导致deadlock。维基百科上给了段示例代码:

      1. dispatch_queue_t exampleQueue = dispatch_queue_create("com.example.unique.identifier", NULL );
      2. dispatch_sync( exampleQueue,^{
      3. dispatch_sync( exampleQueue,^{
      4. printf("I am now deadlocked...\n");
      5. });});
      6. dispatch_release( exampleQueue );

      如果追求的是并发,那么dispatch_sync有什么用呢?关于dispatch_sync的用途,StackOverFlow是这样讨论的:

      Can anyone explain with really clear use cases what the purpose of dispatch_sync in GCD is 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 queue q. 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中:

      1. -(void)viewDidAppear:(BOOL)animated{
      2. dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      3. dispatch_async(concurrentQueue, ^{
      4. __block UIImage *image = nil;
      5. dispatch_sync(concurrentQueue, ^{
      6. /* 下载图片 */
      7. NSString *urlAsString = @"http://images.apple.com/mac/home/images/promo_lead_macbook_air.jpg";
      8. NSURL *url = [NSURL URLWithString:urlAsString];
      9. NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
      10. NSError *downloadError = nil;
      11. NSData *imageData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&downloadError];
      12. if (downloadError == nil && imageData != nil){
      13. image = [UIImage imageWithData:imageData];
      14. } else if(downloadError!=nil){
      15. NSLog(@"Error happened = %@", downloadError);
      16. }else {
      17. NSLog(@"No data could get downloaded from the URL.");
      18. }
      19. });
      20. //在主队列中把图片展示给用户
      21. dispatch_sync(dispatch_get_main_queue(), ^{
      22. if (image != nil){
      23. /* 创建一个UIImageView */
      24. UIImageView *imageView = [[UIImageView alloc]
      25. initWithFrame:self.view.bounds];
      26. /* 设置图片*/
      27. [imageView setImage:image];
      28. /* 设置图片比例*/
      29. [imageView setContentMode:UIViewContentModeScaleAspectFit];
      30. /* 添加视图 */
      31. [self.view addSubview:imageView];
      32. } else {
      33. NSLog(@"Image isn't downloaded. Nothing to display.");
      34. } });
      35. });
      36. }

      运行结果:

IOS学习之路八(GCD与多线程)的更多相关文章

  1. IOS开发---菜鸟学习之路--(二十二)-近期感想以及我的IOS学习之路

    在不知不觉当中已经写了21篇内容 其实一开始是没有想些什么东西的 只是买了Air后 感觉用着挺舒服的,每天可以躺在床上,就一台笔记本,不用网线,不用电源,不用鼠标,不用键盘,干干脆脆的就一台笔记本. ...

  2. 浅谈iOS学习之路(转)

    转眼学习iOS已经快两年的时间了,这个路上有挫折也有喜悦,一步步走过来发现这个过程是我这一辈子的财富,我以前的老大总是对我说,年轻就是最大的资本(本人91年),现在才算是慢慢的体会到,反观自己走过的这 ...

  3. 浅谈iOS学习之路

    转眼学习iOS已经快两年的时间了,这个路上有挫折也有喜悦,一步步走过来发现这个过程是我这一辈子的财富,我以前的老大总是对我说,年轻就是最大的资本(本人91年),现在才算是慢慢的体会到,反观自己走过的这 ...

  4. IOS7学习之路八(iOS 禁止屏幕旋转的方法)

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { retu ...

  5. IOS学习之路十八(通过 NSURLConnection 发送 HTTP 各种请求)

    你想通过 Http 协议向服务器发送一个 Get 的包装请求,并在这个请求中添加了一些请 求参数. 向远程服务器发送一个 GET 请求,然后解析返回的数据.通常一个 GET 请求是添加了 一些参数的, ...

  6. IOS学习之路--OC的基础知识

    1.项目经验 2.基础问题 3.指南认识 4.解决思路 ios开发三大块: 1.Oc基础 2.CocoaTouch框架 3.Xcode使用 -------------------- CocoaTouc ...

  7. 纪录我的iOS学习之路

    学习资料的网址 田伟宇(Casa Taloyum)有几篇介绍iOS架构的文章,一级棒!原博客链接. iOS应用架构谈 开篇 iOS应用架构谈 view层的组织和调用方案 iOS应用架构谈 网络层设计方 ...

  8. 我的IOS学习之路(三):手势识别器

    在iOS的学习中,对于手势的处理是极为重要的,如对于图片,我们经常需要进行旋转,缩放以及移动等.这里做一下总结,详见代码. - (void)viewDidLoad { [super viewDidLo ...

  9. Java学习笔记(八)——java多线程

    [前面的话] 实际项目在用spring框架结合dubbo框架做一个系统,虽然也负责了一块内容,但是自己的能力还是不足,所以还需要好好学习一下基础知识,然后做一些笔记.希望做完了这个项目可以写一些dub ...

随机推荐

  1. DM8168 layout

    我们学到了以前的系统板的教训,新的版本号DM8168烤... 一级:电源.DM8168.DDR3.FPGA.CPLD.Nandflash.USB.以太网络.SATA.JTAG等待. 的地面电源部充分. ...

  2. 插件式Web框架

    转载构建高性能插件式Web框架 基于MVC插件模式构建支持数据库集群.数据实时同步.数据发布与订阅的Web框架系统.如下图: 1.基于插件式开发 采用插件模式开发的优点是使得系统框架和业务模式有效地进 ...

  3. linux内核源码目录(转)

    Linux用来支持各种体系结构的源代码包含大约4500个C语言程序,存放在270个左右的子目录下,总共大约包含200万行代码,大概占用58MB磁盘空间. 源代码所有在目录:/usr/src/linux ...

  4. 省钱加油(Fuel Economy)题解

    题目 农夫约翰决定去做一个环游国家旅行,为了不让他的奶牛们感到孤单,于是他决定租一辆货车带领他的奶牛们一起去旅行.这辆货车的油箱最多可以承载G 个单位的油,同时为了简化问题,规定每一个单位的油可以行使 ...

  5. EF结合SqlBulkCopy

    EF结合SqlBulkCopy在项目中的使用 这是我第一次写博客,由于水平有限,写不出什么好东西,还望见谅. 我现在参与的这个项目采用的是EF框架,方便了数据库的访问.但在实际中,发现项目中导入市县E ...

  6. 【Unity Shaders】Mobile Shader Adjustment —— 为手机定制Shader

    本系列主要參考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同一时候会加上一点个人理解或拓展. 这里是本书全部的插图.这里是本书所需的代码和 ...

  7. Milo的游戏开发的一些链接资料

    http://www.cnblogs.com/miloyip/default.aspx?page=1 http://www.cnblogs.com/miloyip/archive/2010/06/14 ...

  8. YII相关资料(干货)

    Sites 网站 yiifeed:Yii 最新动态都在这里 yiigist:Yii 专用的 Packages my-yii:Yii 学习资料和新闻 Docs 文档 Yii Framework 2.0 ...

  9. 快速构建Windows 8风格应用16-SettingContract原理及构建

    原文:快速构建Windows 8风格应用16-SettingContract原理及构建 本篇博文主要介绍Setting Contract概述.Setting Contract实现基本原理.如何构建Se ...

  10. 快速构建Windows 8风格应用31-构建磁贴

    原文:快速构建Windows 8风格应用31-构建磁贴 引言 磁贴是吸引用户经常使用应用重要手段之一.我们可将应用程序内较好的内容使用磁贴进行展示. 另外应用程序磁贴是应用程序中的核心部分,而且很可能 ...