牛逼的中枢调度器

简介

  • GCD是苹果公司为多核的并行运算提出的解决方案
  • GCD会自动利用更多的CPU内核(比如双核、四核)
  • GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
  • GCD是纯C语言实现的,提供了非常多强大的函数

核心概念

GCD中有两个核心概念:

  • 任务:执行什么操作
  • 队列:用来存放任务

GCD的使用步骤

  1. 指定任务,确定想做的事情
  2. 将任务添加到队列中,GCD会自动将队列中的任务取出来放到对应的线程中执行。队列的取出遵循队列的FIFO原则:先进先出,后进后出

执行任务

GCD中有两个可以用来执行任务的函数

  • 用同步的方式执行任务:只能在当前线程中执行,不会开其他线程
//queue:队列;block:任务
void dispatch_sync(dispatch_queue_t queue,dispatch_block_t block);
  • 用异步的方法执行任务:可以在新的线程中执行任务,具备开启新线程的能力
//queue:队列;block:任务
void dispatch_async(dispatch_queue_t queue,dispatch_block_t block);

队列的类型

GCD中的队列可以分为两大类型:

  • 并发队列(concurrent dispatch queue):可以让队列任务并发(同时)执行(自动开启多个线程同时执行任务),并发功能只有在异步函数(dispatch_asyns)中才有效

    • GCD默认已经提供了全局的并发队列,提供整个应用使用,不需要手动创建。

      dispatch_queue_t dispatch_get_global_queue(dispatch_queue_t
      priority,unsigned long flags);
      //priority:队列的优先级,flags:此参数暂时没有使用,传0即可
      
  • 串行队列(serial dispatch queue):让任务一个接着一个地执行(一个任务执行完毕后,在执行下一个任务)。GCD有两种方式获得串行队列

    • 使用dispatch_queue_create函数手动创建串行队列
    dispatch_queue_t dispatch_queue_create(const char
    *label,dispatch_queue_create_attr_t attr);
    //label:队列名称,attr:队列属性,一般用NULL即可
    
    • 使用主队列(跟主线程相关的队列):主队列是GCD中的自带的一种特殊的串行队列,放在主队列中的任务,都会放到主线程中执行。
    dispatch_queue_t dispatch_get_main_queue(void);
    
      *注意*:
      
      1.  //主队列(添加到主队列中的任务,都会自动添加到主线程中执行)
      
          dispatch_queue_t queue = dispatch_get_main_queue();
      2.  //添加任务到主队列中异步执行,该异步功能失效
      
          dispatch_async(queue,^{任务});
      3.  //添加任务到主队列中同步执行,改同步功能会卡死
      
          Dispatch_sync(queue,^{任务});
    

总结

  • 同步和异步主要影响能不能开启新的线程:同步在当前线程中执行任务,不具备别开启新线程的能力;异步能在新线程中执行任务,具备开启新线程的能力

    dispatch_sync: 同步,不具备开启线程的能力

    dispatch_async:异步,具备开启线程的能力

  • 并发和串行主要影响任务的执行方式:并发是多个任务同时执行;串行是一个执行完毕后,在执行下一个任务。

    //获得全局的并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
    //创建一个串行队列
    dispatch_queue_t queue = dispatch_queue_create("name.queue",NULL);
    //主队列(添加到主队列中的任务,都会自动方法主线程中执行)
    dispatch_queue_t queue = dispatch_get_main_queue();
    

使用例子

  1. 同步函数+主队列
-(void)syncMain{
    NSLog(@"begin");
    
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    dispatch_sync(queue,^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_sync(queue,^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    dispatch_sync(queue,^{
        NSLog(@"3---%@",[NSThread currentThread]);
    });
    
    NSLog(@"end");
    
    //注意:使用sync函数往当前队列中添加任务,会卡住当前的串行队列,除了begin其他都不会被打印。
}
  1. 异步函数+主队列
- (void)asyncMain
{
    
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    dispatch_async(queue, ^{
        NSLog(@"1-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"3-----%@", [NSThread currentThread]);
    });
    
    //注意:不会开启新线程。只会在主队列中执行,失去了异步函数的功能。
}
  1. 同步函数+串行队列
-(void)syncSerial{

    dispatch_queue_t queue = dispatch_queue_create("com.queue",DISPATCH_QUEUE_SERIAL);
    
    dispatch_sync(queue,^{
        NSLog(@"1---%@",[NSThread currentThread]);
    })
    dispatch_sync(queue,^{
        NSLog(@"2---%@",[NSThread currentThread]);
    })
    dispatch_sync(queue,^{
        NSLog(@"3---%@",[NSThread currentThread]);
    })
    
    //注意:不会开启新的线程,在当前线程执行任务。任务是串行的,执行完一个任务,再执行下一个任务
}
  1. 异步函数+串行队列
- (void)asyncSerial
{
    
    dispatch_queue_t queue = dispatch_queue_create("com.queue", DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(queue, ^{
        NSLog(@"1-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"3-----%@", [NSThread currentThread]);
    });
    
    注意:会开启新的线程,但是任务是串行的,执行完一个任务,再执行下一个任务
}
  1. 同步函数+并发队列
- (void)syncConcurrent
{
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_sync(queue, ^{
        NSLog(@"1-----%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2-----%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"3-----%@", [NSThread currentThread]);
    });
    
    //注意:不会开启新的线程。串行执行任务。
}

  1. 异步函数+并发队列:可以同时开启多条线程,是最常用的方式
- (void)asyncConcurrent
{
    // 1.获得全局的并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    // 2.将任务加入队列
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<10; i++) {
            NSLog(@"1-----%@", [NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<10; i++) {
            NSLog(@"2-----%@", [NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<10; i++) {
            NSLog(@"3-----%@", [NSThread currentThread]);
        }
    });
    

各种队列的执行效果

全局并发队列 手动创建串行队列 主队列(串行队列)
同步(sync) 不会开启新线程串行执行任务 没有开启新线程串行执行任务 没有开启新线程串行执行任务会卡死
异步(async) 有开启新线程并发执行任务 有开启新线程串行执行任务 没有开启新线程串行,执行任务

GCD的其他用法

用法一

// 作用:在并行队列中,等待前面的所有并行操作完成,然后执行dispatch_barrier_async中的操作,然后恢复原有执行状态,继续并行执行
void dispatch_barrier_async(dispatch_queue_t queue,dispatch_block_t block);

用法二

//作用:延迟执行
void dispatch_after(dispatch_time_t when,dispatch_queue_t queue,dispatch_block_t block);

用法三

//作用:block中的代码块只被执行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
    //需要执行的代码块
});

用法三

    //作用:文件剪切,快速迭代
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    NSString *from = @"/Users/Anthony/Desktop/From";
    NSString *to = @"/Users/Anthony/Desktop/To";
    
    NSFileManager *mgr = [NSFileManager defaultManager];
    NSArray *subPaths = [mgr subpathsAtPath:from];
    
    dispatch_apply(subPaths.count, queue, ^(size_t index) {
       
        NSString *subPath = subPaths[index];
        NSString *fromFullPath = [from stringByAppendingPathComponent:subPath];
        NSString *toFullPath = [to stringByAppendingPathComponent:subPath];
        
        [mgr moveItemAtPath:fromFullPath toPath:toFullPath error:nil];
        
        NSLog(@"%@--%@",[NSThread currentThread],subPath);
    });
    

用法四

//队列组
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);�dispatch_group_t group = dispatch_group_create();
//下载图片
dispatch_group_async(dispatch_group_t group,dispath_queue_t queue,^{});
//(保证执行完组里面的所有任务之后,再执行notify函数里面的block)
dispatch_group_notify(dispatch_group_t group,
dispatch_queue_t queue,
dispatch_block_t block);

你可能感兴趣的:(牛逼的中枢调度器)