`
mmdev
  • 浏览: 12914000 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

IOS学习之十七:Grand Central Dispatch(GCD)编程基础

 
阅读更多

有过编程经验的人,基本都会接触到多线程这块。

在java中以及Android开发中,大量的后台运行,异步消息队列,基本都是运用了多线程来实现。

同样在,在ios移动开发和Android基本是很类似的一种模型。

但是很多时候,在应用开发中,我们会发现本身并没有自己编码去处理一些并发的事件,去开辟新的子线程等等。

(虽然一般的调用sdk发起一个网络请求,系统都是会默认给你新起一个线程去处理的)。

整个程序看上去基本就是在Main线程中执行。

确实也是这样的一种现象,因为我们基本都是在操作控件的布局,对控件数据添加,对于UI对象的更新都是在主线程的进行。

即便等下我们看到我们开启了一个新的子线程用来获取处理数据,最后还是需要通过通知UI主线程来刷新。

当然了,ios本身也是和大部分语言一样,有NSThread线程类(我们都知道java中我们用到这个类)。

这些系统比较底层的api类,可以被我用来书写自己的并发线程和操作队列。

学过Android的我们都知道Handler,Looper这个概念,Looper说白了就是一个主线程的消息循环队列,handler一般理解就是用于子线程和UI主线程一些数据交互。

看了下ios的GCD特性,发现他们之间颇有几分相似。


1.下面来看下如何使用gcd编程的异步

    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // 处理耗时操作的代码块...
        
        //通知主线程刷新
        dispatch_async(dispatch_get_main_queue(), ^{
            //回调或者说是通知主线程刷新,
        });
        
    });

dispatch_async开启一个异步操作,第一个参数是指定一个gcd队列,第二个参数是分配一个处理事物的程序块到该队列。

dispatch_get_global_queue(0, 0),指用了全局队列。

一般来说系统本身会有3个队列。

global_queue,current_queue,以及main_queue.

获取一个全局队列是接受两个参数,第一个是我分配的事物处理程序块队列优先级。分高低和默认,0为默认2为高,-2为低

#define	DISPATCH_QUEUE_PRIORITY_HIGH 	 2
#define	DISPATCH_QUEUE_PRIORITY_DEFAULT  0
#define	DISPATCH_QUEUE_PRIORITY_LOW 	(-2)

处理完事物后,需要将结果返回给或者是刷新UI主线程,同样,和上面一样,抓取主线程,程序块操作。


//天啊,手贱不小心点到了home间,会退后发现没保存~~~写的并发一块内容都没了!!!

二:GCD之并发概念

其实对于编程中,我们一直提及到的几个概念,同步,异步,并发,锁等。

有时觉得一下子还真说不清。


下面我们以上面提到的图片加载来看下这3个概念我的理解

1同步:

   for (int i = 0 ; i < 10; i++) {
      
         UIImage *img = [self getImgeWith:[urlArr objectForIndex:i]];
          [myImgV[i] setImage:img];
        
    }

假设我要加载10个图片,我现在拥有这些图片的资源地址,保存在一个数组中。

我们先以获取第一张图片来举例:

同步执行的概念就是,我获取完第一张图片的,

执行了for循环第一句返回了img后,我才能执行第二句,UI界面的刷新。

如果第一句返回的时间需要10秒,那我程序的响应就仿佛一直卡在这里一样,我无法进行其他操作。必须等它返回!!

因此,同步的一个很好理解的感念就是,一步走到黑。

2.异步

  for (int i = 0 ; i < 10; i++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // 处理耗时操作的代码块...
         UIImage *img = [self getImgeWith:[urlArr objectForIndex:i]];
        //通知主线程刷新
        dispatch_async(dispatch_get_main_queue(), ^{
            //回调或者说是通知主线程刷新,
              [myImgV[i] setImage:img];
        });
        
    });

看了这代码,我们会说,异步操作那个假设还是要10秒啊,总体看来,执行一张图片的时间加载还是要在10秒左右啊,

貌似异步没什么鸟用么。但是,别忽略了其中一点,也黑丝核心的一点,此时我们图片获取操作放在里一个线程队列里,

此刻,虽然我们看着图片的加载还是需要10秒才会出来,但是,在这10秒期间,我们的UI主线程是可以操作的,比如界面上有个按钮,你是可以按的

而不是如上面的同步,在10面期间,我是只能干等着,什么都做不了。

异步的核心概念就是一个新线程,一个消息回调通知。

3.并行

我们还是以上代码为例。前面我强调了,我们只看一张图片的加载,现在,回到我们第一眼看到代码的思维上去,

一个for循环。其实上面代码过后,我是创建了10个异步线程。

好吧,到此,我们应该明白这三个概念了。

同步,其实我前面的例子举得有些局限,就是这个例子本身就说明不需要同步执行,然后给大家大感觉是

同步是编程中一个忌讳点一样,其实不然,很多时候。我们真是需要同步来做一些限制(比如线程中提出的同步锁?听着就感觉有用么

虽然可能并不如我们想的那样的运用同步,但是至少说明这个概念同样是有用的)

我还是以刚才那个加载图片为例子,来个简单的说明如何运用同步的好处。

当然,我只是模拟一个同步的情况。

假设我们现在图片的加载是这样的,图片本身为在加载前是一个默认的图片,上面写着,点击我加载,点击后会调用网络加载方法,然后图片显示加载中,

然后我们双击图片时(当然,理论上是在加载完后)读取图片网络图片放大,好吧,到这里应该能想到要表达的情况了。

整个流程应该是点击图片->加载->双击查看。那如果成了点击->加载中(以返回了图片的作者和信息)-》双击图片(通过前面请求返回的大图链接显示大图)-》

完全加载返回(返回了大图链接)。此时我们看不到图像的大图了。因为我们操作在返回前了,也就是说,

很多时候,我们下一个动作的操作必须需要用到前面一个操作的数据时,我们会给他做认为的同步编程,比如加个按钮锁。

这是我们又会疑惑道,下一个执行需要用到前一个执行的,那第一个例子中的for循环的第二句不是要用到么,这么说

他们必须要同步啊,如果你这么想了,好巧,我们想到一块去了~

但是,注意,前面我们到的异步是为了解决我点击其他按钮的操作,而不是说更新UI操作。下载和更新UI操作在我们看来必须是同步的

这是对的,但是那种做导致了系统本身一些监听事件监听到点击处理在那个请求之后了,这边的加载图片其实要看成一次事件执行,

因为对于事件的这一抽象单元,其实是一种可人为定义的宽广度。

也就是说,一次数据获取和图像填充,其实算是一个图像获取加载事件,事件可以说包含两个单元,加载和填充。

而整个这个事件对于我们点击其他按钮并无关系,那么也就说明了无需同步。

有道理啊,但是若果我们要点击这个图片呢,也就是回到刚才那个可以双击的假设。

此处也许我么又忽略了一点为什么加载中我们能点击双击呢,也就这样的假设是获取图片已经做了异步,但是我们下一步操作又是需要同步的

因此做了人为的同步锁定。

好了,说的太多了,当时至少我们明白两点

异步可能是为了反正耗时操作造成的主线程堵塞,

同步是为了解决一些不必要错误和麻烦。也许到这里,我们脑中会联想到的所谓的线程安全性。

其实同步以及同步锁,却是应该是考虑到这样的不必要和不安全因素。


最后在简单阐述下异步和并发关系。

其实看了上面说的,异步只是提供了一种多线程处理的概念,

并发是更像是异步的一种大规模实现。

就好比说,异步提出了可以用小弟去收保护费,收完了告诉并交给自己,而我在期间做其他要做的事。

并发突然想到,异步这个很有道理啊,那我有4个地方要收,一个小弟去收,虽然我还是可以闲着做其他的事,

但是小弟跑四个地方,我拿到钱所需要的时间还是和我自己去收一样的,只不过我不用那么费劲了,还能做其他事了。

因此,并发觉得应该派四个小弟去,因为每个场地的保护费各不相干的。(刚看了个纽约黑帮~)。


因此说,异步解决了线程堵塞,而并发则是在异步的基础上,提高了符合特性事件的处理时间效率。


当然,如果10个图片本身相互间是没什么联系,但是,最后一个事件需要处理计算这10个图片的总容量值。

那么可以用dispatch_group_async。

具体就看文档吧。


总体来说,看了iosGCD这块,一是让我熟悉了block编程特性,还有是熟悉如何使用ios提供的GCD特性

来完成多线程编程。





分享到:
评论

相关推荐

    Grand Central Dispatch(GCD)介绍要点难点案例分享代码解析

    全称:Grand Central Dispatch(GCD) 定义:GCD是苹果公司开发的一套多线程编程的API,用于简化多线程编程的复杂性。 功能:GCD提供了一个易于使用的、基于任务的并发模型,可以将任务提交给系统,系统会自动管理...

    GCD IOS example

    Grand Central Dispatch (GCD)是异步执行任务的技术之一。一般将应用程序中记述的线程管理用的代码在系统级中实现。由于线程管理是作为系统的一部分来实现的,因此可统一管理,也可执行任务,这样就比以前的线程更...

    iOS多线程GCD和线程锁的使用

    iOS多线程编程之Grand Central Dispatch(GCD)使用,卖票的例子来讲NSThread的线程同步,使用了两种锁,一种NSCondition ,一种是:NSLock,还有加了一个 线程3 去唤醒其他两个线程锁中的wait,里面的注释很已经写的...

    iOS多线程编程之NSThread的使用案例

    2、Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue的使用)3、GCD 全称:Grand Central Dispatch( iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用) 这三种编程方式从上到下,抽象度...

    多线程GCD的使用

    iOS多线程编程之Grand Central Dispatch(GCD)使用,具有1、常用的方法dispatch_async 2、dispatch_group_async 3、dispatch_barrier_async 4、dispatch_apply的用法

    ios 多线程编程指南.pdf

    如操作对象(Operation objects)和Grand Central Dispatch(GCD),提供一个更加现代化和高效率的基础设施来实现多核并发,但是Mac OS X和iOS也提供一套接口来创建和管理线程。 本文档介绍了Mac OS X上面的可用线程...

    iOS 多线程编程指南 中文版

    虽然更新的技术 如操作对象(Operation objects)和 Grand Central Dispatch(GCD),提供一个更 加现代化和高效率的基础设施来实现多核并发,但是 Mac OS X 和 iOS 也提供一套接 口来创建和管理线程。 本文档介绍了 Mac ...

    IOS 多线程GCD详解

    Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。 dispatch queue分成以下三种: 1)运行在主线程的Main queue,通过dispatch_get_main_queue获取。 #definedispatch_get_main_queue() \DISPATCH...

    ios 多线程编程指南

    线程是单个应用中可以并发执行多个代码路径的多种技术之一。虽然更新的技术 如操作对象(Operation objects)和 Grand Central Dispatch(GCD),

    Async.OC:Objective-C中的语法糖,用于Grand Central Dispatch中的异步调度

    异步OC 用Objective-C重写... 代替熟悉的GCD语法: dispatch_async (dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{ NSLog ( @" A: This is run on the background " ); dispatch_async ( dis

    Mac.OS.X和iOS中的并行开发

    This concise book shows you how to use Apple's Grand Central Dispatch (GCD) to simplify programming on multicore iOS devices and Mac OS X. Managing your application’s resources on more than one ...

    Concurrency by Tutorials - iOS 并发编程指南 (EPub格式)

    了解Grand Central Dispatch,Apple对C的libdispatch的实现,也称为GCD,因为它是排队任务并行运行的最简单方法之一。 然后,当GCD没有完全削减它时,采取操作和操作队列; 您将学习如何进一步定制和重用您的并发...

    iOS多线程编程指南

    线程是单个应用中可以并发执行多个代码路径的多种技术之一。虽然更新的技术 如操作对象(Operation objects)和 Grand Central Dispatch(GCD),

    Pro Multithreading and Memory Management for iOS and OS X

    Pro Multithreading and Memory Management for iOS and OS X with ARC, Grand Central Dispatch, and Blocks

    详解iOS多线程GCD问题

    GCD是Grand Central Dispatch的简称,它是基于C语言的。如果使用GCD,完全由系统管理线程,我们不需要编写线程代码。只需定义想要执行的任务,然后添加到适当的调度队列(dispatch queue)。GCD会负责创建线程和调度你...

    iOS应用程序中通过dispatch队列控制线程执行的方法

    Grand Central Dispatch简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其他的对称多处理系统的系统,iOS应用程序中通过dispatch队列控制线程执行则是以并发来达到多核优化的重要途径.

    详解iOS多线程GCD的使用

    Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法,本文给大家详细介绍IOS中GCD的使用,需要的朋友参考下

    详解IOS中GCD的使用

    Grand Central Dispatch(GCD)是异步执行任务的技术之一。一般将应用程序中记述的线程管理用的代码在系统级中实现。开发者只需要定义想执行的任务并追加到适当的Dispatch Queue中,GCD就能生成必要的线程并计划执行...

    多线程编程指南

    线程是单个应用中可以并发执行多个代码路径的多种技术之一。虽然更新的技术 如操作对象(Operation objects)和 Grand Central Dispatch(GCD),

    CFHipsterRef

    Grand Central Dispatch Inter-Process Communication CoreServices ImageI/O Accelerate Security SystemConfiguration International Components for Unicode DictionaryServices Xcode Toolchain Third-Party ...

Global site tag (gtag.js) - Google Analytics