当前位置: 代码迷 >> 综合 >> iOS多线程开发(五)---GCD(Grand Central Dispatch)
  详细解决方案

iOS多线程开发(五)---GCD(Grand Central Dispatch)

热度:35   发布时间:2023-12-11 14:35:45.0

GCD 原理

-将一段(Block)代码作为特定任务,放到指定的队列(queue:Serial(串行,同时只能执行一个任务)/globel(并行,同时可执行多个任务,但执行顺序是随机的)/main(全局的Serial,在主线程里面执行任务) dispatch queue)里,进行同步/异步(dispatch_sync/dispatch_async)处理。根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。dispatch_sync/dispatch_async的意思就是将任务进行同步/异步并行处理,不一定需要一个任务处理完后才能处理下一个

-一个任务可以是一个函数(function)或者是一个block。 GCD的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节。

GCD 概述

1. GCD 包含于 libSystem.dylib

2. 可供所有程序使用.

- #include <dispatch/dispatch.h>

3. GCD API 提供 block-based and function-based variants

- 目前仅提供 block-based API

GCD总结

1. Blocks

- dispatch_async()

2. Queues

- Lightweight list of blocks

- Enqueue/dequeue is FIFO

-dispatch queue分为下面三种:

   -Serial 又称为private dispatch queues,同时只执行一个任务。Serial queue通常用于同步访问特定的资源或数据。当你创建多个Serial queue时,虽然它们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。

   -Concurrent 又称为global dispatch queue,可以并发地执行多个任务,但是执行完成的顺序是随机的。

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

3. dispatch_get_main_queue()

- Main thread/main runloop(获取主线程的队列)

4. dispatch_queue_create()

- Automatic helper thread, private dispatch queues

GCD的好处

1. 高效 - More CPU cycles available for your code

2. 使用方便

- Blocks are easy to use

- Queues are inherently producer/consumer

3. Systemwide perspective

- Only the OS can balance unrelated subsystems

兼容性

1. Existing threading and synchronization primitives are 100% compatible

2. GCD threads are wrapped POSIX threads

- Do not cancel, exit, kill, join, or detach GCD threads

3. GCD reuses threads

- Restore any per-thread state changed within a block

多线程

Session 206已提到此内容。

锁定资源

1. 对关键资源进行互斥访问。

2. 在线程中按序访问共享资源。

3. Ensure data integrity

没有GCD的代码

- (void)updateImageCacheWithImg:(UIImage*)img
{
  NSLock *nLock = self.imageCacheLock;
  [nLock lock];
  // Critical section
  if ([self.imageCache containsObj:img])
  {
    [nLock unlock]; // Don't forget to unlock
    return;
  }
  [self.imageCache addObj:img];
  [nLock unlock];
}

GCD代码

- (void)updateImageCacheWithImg:(NSImage*)img

{

     dispatch_queue_t queue = self.imageCacheQueue;

     dispatch_sync(queue, ^{ //You can change dispatch_sync to dispatch_async to defer critical section

         // Critical section

         UIImage *cellImage = [self loadMyImageFromNetwork:image_url];

         // 将图片cache到本地

         [self cacheImage:cellImage];

         if ([self.imageCache containsObj:cellImage]) {

             return;

          }

          [self.imageCache addObj:cellImage];

          });

}

dispatch_sync/dispatch_async的意思就是将任务进行同步/异步并行处理,不一定需要一个任务处理完后才能处理下一个。以上代码loadMyImageFromNetwork的意思就是从网络中读取图片,这个任务交给network_queue来处理。这样读取图片的时间过长也不会阻塞主线程界面的处理。

  • dispatch_async(network_queue, ^{    
  •     UIImage *cellImage = [self loadMyImageFromNetwork:image_url];    
  •     // 将图片cache到本地    
  •     [self cacheImage:cellImage];    
  •     
  •    // 回到主线程    
  •    dispatch_async(dispatch_get_main_queue(), ^{    
  •       // 显示图片到界面    
  •       [self displayImageToTableView:cellImage];    
  •    }];    
  •         
  • } );  
  • 线程间通信

通过以下方法 (Without GCD)

– performSelectorOnMainThread:withObject:waitUntilDone:

– performSelector:onThread:withObject:waitUntilDone:

– performSelector:withObject:afterDelay:

– performSelectorInBackground:withObject:

GCD 代码,等同于 performSelector:onThread:withObject:waitUntilDone:

// waitUntilDone: NO

dispatch_async(queue, ^{

[myObject doSomething:foo withData:bar];

});

// waitUntilDone: YES

dispatch_sync(queue, ^{

[myObject doSomething:foo withData:bar];

});

GCD代码, 等同于 performSelector:withObject:afterDelay:

dispatch_time_t delay;

delay = dispatch_time(DISPATCH_TIME_NOW, 50000 /* 50μs */);

dispatch_after(delay, queue, ^{ [myObject doSomething:foo withData:bar];});

GCD代码,等同于 performSelectorInBackground:withObject:

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

dispatch_async(queue, ^{ [myObject doSomething:foo withData:bar];});
Global Queues

1. Enqueue/dequeue is FIFO


2. Concurrent execution- Non-FIFO completion order


3. dispatch_get_global_queue(priority, 0)
4. Global queues map GCD activity to real threads

5. Priority bands- DISPATCH_QUEUE_PRIORITY_HIGH - DISPATCH_QUEUE_PRIORITY_DEFAULT - DISPATCH_QUEUE_PRIORITY_LOW
下面三节讲述了很多内容,但我还没有理解。如有兴趣,请看原始视频。- Dispatch Sources
- Source Cancellation- Target Queues

GCD对象

GCD方法大全


管理对象的生命周期

1. Ensure objects captured by blocks are valid when blocks are executed

- Objects must be retained and released around asynchronous operations

2. Objective-C objects captured by blocks are auto-retained and auto-released

3. Other objects captured by blocks must be retained by your code

- CFRetain()/CFRelease()

- dispatch_retain()/dispatch_release()

挂起和恢复

1. Suspend and resume only affects queues and sources you create

- Sources are created suspended

2. Suspension is asynchronous

- Takes effect between blocks

3. Your queues can predictably suspend objects that target them

程序上下文

1. Applications can attach custom data to GCD objects

- dispatch_set_context()/dispatch_get_context()

2. Optional finalizer callback

- dispatch_set_finalizer_f()

- Allows attached context to be freed with object

- Called on the target queue of the object

WWDC2010 Session211 Simplifying iPhone App Development with Grand Central Dispatch

Daniel Steffen - Core OS

  相关解决方案