多线程——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,^{});

 


你可能感兴趣的:(多线程——GCD)