GCD

GCD的工作原理是:让任务平行排队,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。

GCD中的FIFO队列称为dispatch queue,它可以保证先进来的任务先得到执行。

dispatch queue分为下面三种:

Serial(串行队列):又称为private dispatch queues,同时只执行一个任务。Serial queue通常用于同步访问特定的资源或数据。

          当创建多个Serial queue时,虽然它们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。

Concurrent(并行队列):队列中可以并发地执行多个任务,但是执行完成的顺序是随机的。

系统同时提供给好几个并发队列。它们叫做全局调度队列(Global Dispatch Queues) 。

目前的四个全局队列有着不同的优先级:background、low、default 以及 high。Apple 的 API 也会使用这些队列,所以添加的任何任务都不会是这些队列中唯一的任务。

Main dispatch queue:它是全局可用的serial queue,它是在应用程序主线程上执行任务的。

dispatch_once_t:保证执行唯一:例如创建单例

//静态变量,保证只有一份实例,才能确保只执行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
   //单例代码 
});
dispatch_queue_create:创建队列
//串行队列
dispatch_queue_t queue = dispatch_queue_create("Queue", DISPATCH_QUEUE_SERIAL);
//并行队列
dispatch_queue_t queue = dispatch_queue_create("Queue", DISPATCH_QUEUE_CONCURRENT);
 
dispatch_after是延迟提交,不是延迟运行
dispatch_suspend,dispatch_resume提供了“挂起、恢复”队列的功能,简单来说,就是可以暂停、恢复队列上的任务。但是这里的“挂起”,并不能保证可以立即停止队列上正在运行的block。
文档指出,dispatch_suspend并不会立即暂停正在运行的block,而是在当前block执行完成后,暂停后续的block执行。
 
用 dispatch_async 处理后台任务

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 

    do .......

        dispatch_async(dispatch_get_main_queue(), ^{

            [self doSomthing];

        }); 

    });

 

首先将工作从主线程移到全局线程。因为这是一个 dispatch_async() ,Block 会被异步地提交,意味着调用线程地执行将会继续。

dispatch_async 添加一个 Block 到队列后就立即返回了。任务会在之后由 GCD 决定执行。当需要在后台执行一个基于网络或 CPU 紧张的任务时就使用 dispatch_async ,这样就不会阻塞当前线程。

 

dispatch_sync(): 同步地提交工作并在返回前等待它完成。使用 dispatch_sync 跟踪你的调度障碍工作,或者当你需要等待操作完成后才能使用 Block 处理过的数据。

 

 

dispatch_sync()dispatch_async() 实例分析

 

 

dispatch_sync例

  1. - (void)viewDidLoad 
  2.   [super viewDidLoad]; 
  3.   dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 
  4.       NSLog(@"First Log"); 
  5.   }); 
  6.   NSLog(@"Second Log"); 
1. 主队列一路按顺序执行任务——接着是一个实例化 UIViewController 的任务,其中包含了 viewDidLoad 。
2. viewDidLoad 在主线程执行。
3. 主线程目前在 viewDidLoad 内,正要到达 dispatch_sync 。
4. dispatch_sync Block 被添加到一个全局队列中,将在稍后执行。进程将在主线程挂起直到该 Block 完成。
  同时,全局队列并发处理任务;要记得 Block 在全局队列中将按照 FIFO 顺序出列,但可以并发执行。
5. 全局队列处理 dispatch_sync Block 加入之前已经出现在队列中的任务。
6. 终于,轮到 dispatch_sync Block 。
7. 这个 Block 完成,因此主线程上的任务可以恢复。
8. viewDidLoad 方法完成,主队列继续处理其他任务。
 
dispatch_async 例:

- (void)viewDidLoad 

  [super viewDidLoad]; 

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 

      NSLog(@"First Log"); 

  }); 

  NSLog(@"Second Log"); 

}

1.主队列一路按顺序执行任务——接着是一个实例化 UIViewController 的任务,其中包含了 viewDidLoad 。

 

2. viewDidLoad 在主线程执行。

 

3.主线程目前在 viewDidLoad 内,正要到达 dispatch_async 。

 

4.dispatch_async Block 被添加到一个全局队列中,将在稍后执行。

 

5.viewDidLoad 在添加 dispatch_async 到全局队列后继续进行,主线程把注意力转向剩下的任务。
  同时,全局队列并发地处理它未完成地任务。记住 Block 在全局队列中将按照 FIFO 顺序出列,但可以并发执行。

 

6.添加到 dispatch_async 的代码块开始执行。

 

7.dispatch_async Block 完成,两个 NSLog 语句将它们的输出放在控制台上。
 
两条语句的输出顺序并不总是一样的。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
 
 

posted on 2016-08-03 17:13  自渔  阅读(216)  评论(0编辑  收藏  举报

导航