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. ACM之跳骚---ShinePans

    Description Z城市居住着非常多仅仅跳蚤.在Z城市周六生活频道有一个娱乐节目.一仅仅跳蚤将被请上一个高空钢丝的正中央.钢丝非常长,能够看作是无限长.节目主持人会给该跳蚤发一张卡片.卡片上写有 ...

  2. jQuery性能优化38建议---最引人注目的用户体验!

    一.需要注意的是的定义jQuery当变量被添加varkeyword 然而,这并不jQuery.整个javascript开发过程,所有需要注意,一定不要将其定义为下面的示例: $loading = $( ...

  3. Android MediaPlayer 和 NativePlayer 播放格式控制

    对于本机MediaPlayer 支持格型式试验: 对于原生 NativeMedia 的支持格式測试: 这个支持就比較失望了,眼下測试的手机仅仅支持 H.264视频及AAC音频,其他的格式都不支持. 使 ...

  4. android屏蔽home键的实现

    Android中,网上很多屏蔽Home键都智能在4.0以下运行,在4.0以及以上运行直接崩溃. 需要这样更改(来源:http://androidmaster.iteye.com/): @Overrid ...

  5. 微信公众平台接口,asp.net实现

    原文:微信公众平台接口,asp.net实现 我为自己的笑话网开发了一个微信公众平台的接口,在这里分享给大家,希望能对朋友们有帮助,如果有什么地方写的不好,好请大家指点! 首先是要进行认证,认证的时候, ...

  6. HDU5014Number Sequence(贪心)

    HDU5014Number Sequence(贪心) 题目链接 题目大意: 给出n,然后给出一个数字串,长度为n + 1, 范围在[0, n - 1].然后要求你找出另外一个序列B,满足上述的要求,而 ...

  7. Python超级明星WEB框架Flask

    Flask简介 Flask是一个相对于Django而言轻量级的Web框架. 和Django大包大揽不同,Flask建立于一系列的开源软件包之上,这其中 最主要的是WSGI应用开发库Werkzeug和模 ...

  8. 安卓Monkey源码分析之运行流程

    在<MonkeyRunner源码分析之与Android设备通讯方式>中,我们谈及到MonkeyRunner控制目标android设备有多种方法,其中之一就是在目标机器启动一个monkey服 ...

  9. MonkeyImage API 实践全记录

    1.    背景 鉴于网上使用MonkeyImage的实例除了方法sameAs外很难找到,所以本人把实践各个API的过程记录下来然自己有更感性的认识,也为往后的工作打下更好的基础.同时也和上一篇文章& ...

  10. 关于PHP的工作流引擎

    关于PHP的工作流引擎,除了三大主流开源:PorcessMaker(排名第一,因其有拖放式图形定义界面),RadiCore(基于PETRI NET)和CuteFlow以外,另外还有一个不为人知的,但却 ...