GCD

1> 概述数据库

  • Grand Central Dispatch (GCD)是Apple开发的一种多核编程技术。主要用于优化应用程序以支持多核处理器以及其余对称多处理系统。编程

  • GCD提供函数实现多线程开发,性能更高,功能也更增强大。安全

  • 它首次发布在Mac OS X 10.6 ,iOS 4及以上也可用。多线程

 2> 核心概念并发

  • 任务:具备必定功能的代码段。通常是一个block或者函数app

  • 分发队列:GCD以队列的方式进行工做,FIFO异步

  • GCD会根据分发队列的类型,建立合适数量的线程执行队列中的任务async

 3> GCD中的队列函数

  • 串行队列(SerialQueue):一次只执行一个任务。Serial queue一般用于同步访问特定的资源或数据。当你建立多个Serial queue时,虽然它们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。SerialQueue能实现线程同步性能

  • 并行队列(Concurrent):能够并发地执行多个任务,虽然遵照FIFO(先进先出),但因为各个任务被分配到不一样的线程执行,所以其完成时间有可能不一样,即:后分配的任务有可能先执行完成;并发队列必定须要和异步执行的任务(使用dispatch_async())结合起来使用才有意义。

  • 主队列:主队列也是一个串行队列,主队列中的任务都在主线程中执行。

 4> 串行队列(SerialQueue)

  • 第一种:系统提供的建立串行队列的方法,实际上主队列的建立方法
1 // 第一种获取方式:里面的任务是在主线程依次去执行,dispatch_get_main_queue()获取主队列
2 dispatch_queue_t queue = dispatch_get_main_queue();
3 // 往队列里面添加任务
4 dispatch_async(queue, ^{
5 NSLog(@"这是第一个任务,当前线程是:%@, 是否主线程 :%d ", [NSThread currentThread],  [[NSThread currentThread] isMainThread]);
6 });
  • 第二种:本身建立的队列
复制代码
1 // 参数1:队列的名字(苹果推荐使用反向域名去命名)
2     // 参数2:队列的类型(串行队列、并行队列),这种方式建立的队列,它会本身去开辟一个子线程去完成队列里面的任务
3     dispatch_queue_t queue = dispatch_queue_create("com.zf.mySerialQueue", DISPATCH_QUEUE_SERIAL);
4 
5     dispatch_async(queue, ^{
6 NSLog(@"这是第一个任务,当前线程是:%@, 是否主线程 :%d ", [NSThread currentThread],  [[NSThread currentThread] isMainThread]);
7  });
复制代码

5> 并行队列

  • 第一种:系统提供的建立并行队列的方法
复制代码
1 // 参数1:优先级PRIORITY(有四个,没有明显的区别)
2     // 参数2:系统保留字,苹果预留的参数为了之后去使用,目前没有用到,填写0
3     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
4 
5     dispatch_async(oneQueue, ^{
6  NSLog(@"这是第一个任务。。。线程是:%@, 是否主线程:%d", [NSThread currentThread], [[NSThread currentThread] isMainThread]);
7  });
复制代码
  • 第二种:本身建立的队列

  使用的方法同串行队列,只有建立函数参数2给定队列的类型的时候,将DISPATCH_QUEUE_SERIAL替换为DISPATCH_QUEUE_CONCURRENT

复制代码
1 // 参数1:队列的名字(苹果推荐使用反向域名去命名)
2     // 参数2:队列的类型(串行队列、并行队列),这种方式建立的队列,它会本身去开辟一个子线程去完成队列里面的任务
3     dispatch_queue_t queue = dispatch_queue_create("com.zf.mySerialQueue", DISPATCH_QUEUE_CONCURRENT);
4 
5     dispatch_async(queue, ^{
6 NSLog(@"这是第一个任务,当前线程是:%@, 是否主线程 :%d ", [NSThread currentThread],  [[NSThread currentThread] isMainThread]);
7  });
复制代码

6> GCD功能函数

  • dispatch_async(dispatch_queue_t queue, ^(void)block)    // 异步任务,往队列中添加任务,任务会排队执行

  参数1(dispatch_queue_t queue):添加任务的队列

  参数2(^(void)block):Block,主要是在添加过程当中进行一些操做,操做代码就写在Block中

  • dispatch_after()      //往队列中添加任务,任务不但会排队,还会在延迟的时间点执行
复制代码
 1 /*
 2      函数
 3      dispatch_after(dispatch_time_t when, dispatch_queue_t queue, ^(void)block);
 4      
 5      // 系统封装的代码快(通常使用)
 6      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(具体的浮点型数字 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
 7        延迟执行的内容
 8      });
 9      
10      */
11     // 参数1:延迟的时间,使用dispatch_time()初始化
12     // 参数2:队列
13     // 参数3:Block
14     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
15         NSLog(@"3.0秒后");
16     });
复制代码

  dispatch_time(dispatch_time_t when, int64_t delta)对延迟时间进行初始化

  参数1:为起始时间,系统宏定义,通常使用 DISPATCH_TIME_NOW

  参数2:为延迟的具体时间类型为 int64_t,变量的类型为:具体浮点型数字 * 时间单位(系统的宏定义,能够根据实际状况选用)

  • dispatch_apply()    //往队列中添加任务,任务会重复执行n次
复制代码
 1 /*
 2      dispatch_apply(size_t iterations, dispatch_queue_t queue, ^(size_t) {
 3         code
 4      });
 5      */
 6     dispatch_queue_t queue = dispatch_queue_create("com.zf.myQueue", DISPATCH_QUEUE_CONCURRENT);
 7     // 参数1:添加任务的个数
 8     // 参数2:队列
 9     // 参数3:Block,这个Block没有变量名,须要本身添加
10     dispatch_apply(10, queue, ^(size_t index) {
11         NSLog(@"%zu", index);
12     });
复制代码

:函数dispatch_apply()的参数3Block没有变量名,须要本身添加

  • dispatch_group_async()   //将任务添加到队列中,并添加分组标记

  • dispatch_group_notify()    //将任务添加到队列中,当某个分组的全部任务执行完以后,此任务才会执行

  • 复制代码
     1 //    dispatch_group_t主要用于把一些不相关的任务归为一组
     2 //    组里面放的是队列
     3 //    dispatch_group_async做用是往组里面的队列添加任务
     4 //    dispatch_group_notify做用:监听组里面的任务,等到组里面的任务所有执行完成以后,才会执行它里面的任务
     5 
     6     //一、建立队列
     7     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
     8     //二、建立组
     9     dispatch_group_t group = dispatch_group_create();
    10          // 三、往组里面的队列添加任务(注意:在执行notify以前最起码要向队列中放置一个任务才能够,不然,notify里面的任务不会等待小组里面的其余任务执行完才执行。)
    11     dispatch_group_async(group, queue, ^{
    12          NSLog(@"这是第一个任务。。。线程是:%@, 是否主线程:%d", [NSThread currentThread], [[NSThread currentThread] isMainThread]);
    13     });
    14    
    15    dispatch_group_notify(group, queue, ^{
    16         NSLog(@"我是最后一个任务,组里面的其余任务都执行完毕以后,我就会执行");
    17     });
    复制代码
  • dispatch_barrier_async()  //将任务添加到队列中,此任务执行的时候,其余任务中止执行
复制代码
 1 // 数据库的读取。。。能够并发执行,经过 GCD 里面的并行队列去实现
 2 // 数据库的写入。。。。只能串行执行,经过 GCD 里面的串行队列去实现
 3 // 可是真正的项目,确定是既有数据的读取,也有数据库的写入。。。如何解决该问题:dispatch_barrier_async 在它以前的任务能够并发去执行,在他以后的任务也能够去并发执行
 4    dispatch_queue_t queue = dispatch_queue_create("concurrentTest",DISPATCH_QUEUE_CONCURRENT);
 5     dispatch_async(queue, ^{
 6 NSLog(@"这是第一个读取数据的任务。。。线程是:%@, 是否主线程:%d", [NSThread currentThread], [[NSThread currentThread] isMainThread]);
 7     });
 8     
 9     dispatch_barrier_async(queue, ^{
10         NSLog(@"正在在数据库里写东西,不要打扰我");
11     });
12     
13     dispatch_async(queue, ^{
14 NSLog(@"这是第二个读取数据的任务。。。线程是:%@, 是否主线程:%d", [NSThread currentThread], [[NSThread currentThread] isMainThread]);
15     });
复制代码
  • dispatch_once()   //任务添加到队列中,但任务在程序运行过程当中,只执行一次

  dispatch_once: 该函数接收一个dispatch_once用于检查该代码块是否已经被调度的谓词(是一个长整型,实际上做为BOOL使用)。它还接收一个但愿在应用的生命周期内仅被调度一次的代码块。

  dispatch_once 不只意味着代码仅会被运行一次,并且仍是线程安全的,这就意味着你不须要使用诸如@synchronized之类的来防止使用多个线程或者队列时不一样步的问题。

  运用代码(单例的完整定义)

复制代码
 1 static MyHandle *handle = nil;
 2 
 3 + (MyHandle *)sharedMyHandle
 4 {    
 5     // 在GCD中只执行一次,用于记录内容是否执行过
 6     static dispatch_once_t onceToken;
 7     
 8     dispatch_once(&onceToken, ^{
 9         handle = [MyHandle new];
10     });
11     
12     return handle;
13 }
复制代码
  • dispatch_sync()   //同步任务 将任务添加到队列中,block不执行完,下面代码不会执行

  与 dispatch_async() 的区别:

   dispatch_async() 不等 block 体执行完,就去执行下面的代码,会在另外的线程中执行

   dispatch_sync() 会等待 block 体执行完成以后,才会去执行 block 体外面的代码,会在当前的线程中执行,当前线程有多是主线程,也有多是子线程

  • dispatch_async_f()  //将任务添加到队列中,任务是函数非block
复制代码
 1 // 函数
 2 void function(void * str){
 3     NSLog(@"这是一个函数,%s",str);
 4 }
 5 
 6 // 第一个参数:队列
 7 // 第二个参数:函数参数的内容
 8 // 第三个参数:函数
 9 dispatch_queue_t queue  = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
10 dispatch_async_f(queue, @"passValue", function);
相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息