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

        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. }

        运行结果:

GCD与多线程的更多相关文章

  1. iOS-----使用GCD实现多线程

    使用GCD实现多线程 GCD的两个核心概念如下: 队列 队列负责管理开发者提交的任务,GCD队列始终以FIFO(先进先出)的方式来处理任务---但 由于任务的执行时间并不相同,因此先处理的任务并一定先 ...

  2. apple平台下的objc的GCD,多线程编程就是优雅自然。

    在apple的操作系统平台里,GCD使得多线程编程是那么的优雅自然.在传统的多线程编程中,首先要写线程处理循环:之后还有事件队列,消息队列:还要在线程循环中分离事件解释消息,分派处理:还要考虑线程间是 ...

  3. GCD的多线程实现方式,线程和定时器混合使用

    GCD (Grand Central Dispatch) 性能更好,追求性能的话 1.创建一个队列 //GCD的使用 //创建一个队列 dispatch_queue_t queue = dispatc ...

  4. iOS开发中GCD在多线程方面的理解

    GCD为Grand Central Dispatch的缩写. Grand Central Dispatch (GCD)是Apple开发的一个多核编程的较新的解决方法.在Mac OS X 10.6雪豹中 ...

  5. [转]关于GCD与多线程

    GCD是什么,你知道吗?你知道了GCD,你确定你会使用吗? 这一篇文章是站在初学者角度去分析GCD,原因是这个很多iOS开发者根本就没用过,即使用过,不知道其中的原理.讲解之前认识一下什么是线程,为什 ...

  6. GCD网络多线程---同步运行,异步运行,串行队列,并行队列

    总结:同步(无论是串行还是并行)----不又一次开辟子线程 异步(无论是串行还是并行)----开辟子线程 GCD: dispatch queue 主线程的main queue 并行队列 global ...

  7. GCD死锁 多线程

    NSLog("); dispatch_sync(dispatch_get_main_queue(), ^{ // sync同步 main串行 // 同步,异步--线程 同步-主线程 // m ...

  8. IOS学习之路八(GCD与多线程)

    GCD,全称Grand Central Dispath,是苹果开发的一种支持并行操作的机制.它的主要部件是一个FIFO队列和一个线程池,前者用来添加任务,后者用来执行任务. GCD中的FIFO队列称为 ...

  9. GCD实现多线程 实践

    GCD中弹窗的正确写法 - (void)viewDidLoad { //…… if (![self isStartLoading]) [self startLoading:nil]; //loadin ...

随机推荐

  1. 关于重写ID3 Algorithm Based On MapReduceV1/C++/Streaming的一些心得体会

    心血来潮,同时想用C++连连手.面对如火如荼的MP,一阵念头闪过,如果把一些ML领域的玩意整合到MP里面是不是很有意思 确实很有意思,可惜mahout来高深,我也看不懂.干脆自动动手丰衣足食,加上自己 ...

  2. Swift入门教程:基本运算符

    基本运算符 Swift所支持的基本运算符 赋值运算符:= 复合赋值运算符:+=.-= 算数运算符:+.-.*./ 求余运算符:% 自增.自减运算符:++.-- 比较运算符:==.!=.>.< ...

  3. style中position的属性值具体解释

    Position的英文原意是指位置.职位.状态.也有安置的意思.在CSS布局中,Position发挥着非常关键的数据,非常多容器的定位是用Position来完毕. Position属性有四个可选值,它 ...

  4. javascript常用知识点集

    javascript常用知识点集 目录结构 一.jquery源码中常见知识点 二.javascript中原型链常见的知识点 三.常用的方法集知识点 一.jquery源码中常见的知识点 1.string ...

  5. php中utf8 与utf-8

    原文:php中utf8 与utf-8 相信很多程序员刚开始也会有这样的疑惑,如题,我也是.    其实,他们可以这样来区分.    一.在php和html中设置编码,请尽量统一写成“UTF-8”,这才 ...

  6. 使用AndroidStudio快速开发教程

    关于AndroidStudio的使用 参考:http://www.codes51.com/article/detail_98914.html  1.对于开发环境的通性:编写 调试 视图   一般的开发 ...

  7. 经常使用Javascript CDN 对照

    [前言] 请参阅某种网上文章: http://c7sky.com/javascript-libraries-cdn.html 本文加入的各个cdn对一些库的更新情况.以及响应时间. [更新] 发表文章 ...

  8. MongoDB的upsert状态判断和pymongo使用方法

    在mongo中,有一个命令非常的方便,就是upsert,顾名思义就是update+insert的作用 根据条件判断有无记录,有的话就更新记录,没有的话就插入一条记录 upsert的使用方法: Mong ...

  9. Linux下查看使用频率最高的十个命令

    这个shell是在linux吧一个小伙伴发的,链接已找不到,挺有意思的,隔段时间运行一次,可以看看自己最近都干了什么. [shell] history | awk '{CMD[$2]++;count+ ...

  10. HDU 2064 汉诺塔III

    汉诺塔III Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...