多线程——GCD

  GCD是异步执行任务的技术之一。开发者只需要定义想执行的任务并追加到适当的Dispatch Queue中,GCD就能生成必要的线程并计划执行任务。由于线程管理是作为系统中的一部分来实现的,因此可统一管理,也可执行任务,这样就比以前的线程更有效率。相比于其他的多线程方法,GCD提供的系统级线程管理提高执行效率。

  GCD的API

  开发者要做的只是定义想执行的任务并追加到适当的Dispatch Queue 中。

  Dispatch Queue 是执行处理的等待队列。通过dispatch_async函数等API,在Block语法中写下想要执行的处理并将其追加到Dispatch Queue。Dispatch Queue按照追加的顺序(先进先出FIFO,First-In-First-Out)执行处理。在执行处理时存在两种Dispatch Queue,一种是等待现在执行中处理的Serial Dispatch Queue(串行执行),另一种是不等待执行中处理的Concurrent Dispatch Queue(并行执行)。一般来说,只在为了避免多线程更新相同数据时导致数据竞争时使用Serial Dispatch Queue。



  dispatch_queue_create

  通过此函数来生成Dispatch Queue

  dispatch_queue_t   myDispatchQueue = dispatch_queue_create("  ", );

  该函数第一个参数指定Dispatch Queued的名称没有也可以设为NULL,设置一个好的名称在调试的时候会很快的定位问题的所在。

  第二个参数是指定类型,Serial Dispatch Queue时则设置为NULL,如果为Concurrent Dispatch Queue时则设置为DISPATCH_QUEUE_CONCURRENT。

  注意,在使用此函数生成Dispatch Queue时必须由我们手动进行释放。这是因为Dispatch Queue没有具有作为Object-C对象来处理的技术。在使用结束后通过

  dispatch_release(myDispatchQueue);来进行释放


  Main Dispatch Queue/Global Dispatch Queue

  在实际的应用中不用特意的生成Dispatch Queue,系统也会给我们提供几个。那就是Main Dispatch Queue 和 Global Dispatch Queue。

  Main Dispatch Queue是在主线程中执行的Dispatch Queue。因为只有这一个主线程,自然这个就是串行线程了。

  Global Dispatch Queue是所有应用程序都可以用的Dispatch Queue,直接获取就可以了。这个是并行线程。

  获取方法:

  dispatch_queue_t main = dispatch_get_main_queue();

  dispatch_queue_t global = dispatch_get_global_queue(  ,  );

  第一个参数指明了Global Dispatch Queue的执行优先级,一共有四个DISPATCH_QUEUE_PRIORITY_HIGH(最高优先级),DISPATCH_QUEUE_PRIORITY_DEFAULT(默认优先级)
,DISPATCH_QUEUE_PRIORITY_LOW(低优先级),DISPATCH_QUEUE_PRIORITY_BACKGROUND(后台优先级)

  //在默认优先级的Global Dispatch Queue中执行Block

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT),^

  {

       //可执行的处理

       //在Main Dispatch Queue中执行Block

       disptach_async(dispatch_get_main_queue(),^

       {

            //只能在主线程中执行的处理

       });

  });


  dispatch_set_target_queue

  指定线程变更优先级。

  dispatch_set_target_queue(  ,  );

  第一个参数为需要变更优先级的线程,第二个参数为变更目标线程。


  dispatch_after

  这个函数可以用来实现需要指定时间后进行处理的情况。但是要注意的是,这个并不一定能指定时间后执行处理,而只是在指定时间后追加需处理的代码块到Dispatch Queue。所以理论上最快是一添加就立马处理,但不一定每次都是,对于时间有严格要求的并不适用。

  dispatch_time_t  time = dispatch_time(DISPATCH_TIME_NOW , 3ull * NSEC_PER_SEC);

  dispatch_after(time,disptach_get_main_queue(),^

  {

      //可执行的处理

  });

  第一个参数是指定时间用的dispatch_time_t 类型的值。该类型可用dispatch_time函数或者dispatch_walltime函数来得到。

  前一个函数是通常用来计算相对时间,后一个则是用来计算绝对时间。例如指定2015年12月23日11时11分11秒。 


  Dispatch Group

  在使用dispatch_queue_create后需要使用dispatch_release进行释放,如果有多个需要释放的话则会比较麻烦。使用Dispatch Group则会比较方便,可以一次全部释放。

  dispatch_queue_t  queue  =  dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

  dispatch_group_t  group  =  dispatch_group_create(); 

  dispatch_group_async(group,queue,^{  NSLog(@"block1") });

  dispatch_group_async(group,queue,^{  NSLog(@"block2") });

  dispatch_group_notify(group,dispatch_get_main_queue(),^{  NSLog(@"done") });

  dispatch_release(group);

  在追加到Dispatch Queue中的处理全部执行结束时,使用dispatch_group_notify函数会将执行的Block追加到Dispatch Queue中,将第一个参数指定为要监视的Dispatch Group。在追加的全部处理执行结束时,将第三个参数的Block追加到第二个参数的Dispatch Queue中。在dispatch_group_notify函数中不管指定什么样的Dispatch Queue,属于Dispatch Group的全部处理在追加NSLog(@"done")时都已执行结束。


  dispatch_barrier_async

  barrier 作为流程控制的一种方式作用在并行环境中,

  例如有1234四个并行线程,运行时4个任务的完成先后顺序是无法保证的。现在12barrier34,则只有在12任务都完成后将barrier中追加的处理完成后会进行34任务,但是12,34这两块任务内部完成顺序是无法保证的。

  dispatch_barrier_async(queue,^{});


   dispatch_async/dispatch_sync

  dispatch_async函数是将指定的Block“非同步”的追加到Dispatch Queue中。

  dispatch_sync函数是将指定的Block“同步”追加到指定的Dispatch Queue中。在追加的Block结束前,函数会一直等待处理执行结束。

  在使用dispatch_sync函数时要注意,因为这个函数有可能会导致程序死锁。请想清楚后再使用。


  dispatch_apply

  dispatch_apply函数是dispatch_sync函数和Dispatch Group的关联API。该函数按指定的次数将指定的Block追加到指定的Dispatch Queue中,并等待处理执行结束。

  dispatch_apply(  ,  ,  );

  第一个参数为重复的次数,第二个参数为追加对象的Dispatch Queue,第三个参数为追加的处理。例如要对NSArray类对象的所有元素执行处理时,不比一个个的编写for循环。

  dispatch_apply([array count],queue,^(size_t index)

  {

      NSLog(@"%zu:%@",index,[array objectAtIndex:index]);

  });

  由于dispatch_apply和dispatch_sync函数相同,会等待处理执行结束,因此推荐在dispatch_async函数中非同步执行dispatch_apply函数。


  dispatch_once

  dispatch_once函数是保证在应用程序执行中只执行一次指定处理的API。在单例的初始化时通常使用这个函数。

  static dispatch_once_t  once;

  dispatch_once(&once,^{});

 


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容

  • 最近颇花了一番功夫把多线程GCD人的一些用法总结出来,一来帮自己巩固一下知识、二来希望能帮到对这一块还迷茫...
    人活一世阅读 271评论 1 1
  • 目录 一、基本概念1.多线程2.串行和并行, 并发3.队列与任务4.同步与异步5.线程状态6.多线程方案 二、GC...
    BohrIsLay阅读 1,548评论 5 12
  • 一、简介在iOS所有实现多线程的方案中,GCD应该是最有魅力的,因为GCD本身是苹果公司为多核的并行运算提出的解决...
    MYS_iOS_8801阅读 566评论 0 0
  • 0.前言 0.什么是GCD? GCD全程为Grand Central Dispatch,是异步执行的技术之一。一般...
    RadioHeadache阅读 194评论 0 0
  • 基于C接口的线程调度。 dispatch_queue_attr_t : 定义一个queue的时候,用于指定queu...
    lzh_coder阅读 924评论 0 0