iOS多线程笔记2--GCD

dispatch_async,异步任务
dispatch_sync,同步任务

1.异步任务会开启新线程,并行队列线程数不确定,执行完的线程回收前可以被其他任务复用(类似cell重用)。

2.dispatch_get_global_queue(identifier, flags),全局队列
参数flags:iOS预留参数,填0即可。
参数identifier:
Ios7,优先级。

    #define DISPATCH_QUEUE_PRIORITY_HIGH 2   //高优先级
    #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0  ///默认优先级
    #define DISPATCH_QUEUE_PRIORITY_LOW (-2)  //低优先级
    #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN  //后台执行,最慢,CPU切换到的频率很低

Ios8,服务质量。

    QOS_CLASS_USER_INTERACTIVE //用户交互,希望线程被快速执行,不要做耗时操作
    QOS_CLASS_USER_INITIATED   //用户需要的,同样不要使用耗时操作
    QOS_CLASS_DEFAULT    //默认,系统用来重置队列。
    QOS_CLASS_UTILITY  //使用工具,用来做耗时操作
    QOS_CLASS_BACKGROUND //后台执行,线程执行非常慢
    QOS_CLASS_UNSPECIFIED //没有优先级,值为0,可以兼容ios7。

3.并发队列:效率高,消耗大,可以同时调度多个任务。
串行队列:效率低,消耗小,一个任务执行完再调度下一个任务。
全局队列:一个特殊的并发队列,由系统默认创建。
主队列:一个任务执行完再调度下一个任务,不会开启新线程,即使异步任务也会顺序执行,和串行队列类似但有区别。不能在主队列使用同步任务,会造成死锁。

   NSLog(@"任务1");
   dispatch_sync(dispatch_get_main_queue(), ^{
       NSLog(@"任务2");
   });
   NSLog(@"任务3");
  "这里我的理解是:类似优先级反转,任务3在任务2未完成时添加到队列,就会先执行任务3,而由于是依次执行,任务2未完成并返回,
   任务3不能执行,此时任务3未完成,任务2也不能执行"

问:主队列只有一条线程运行,同步和异步有什么区别?异步为什么不死锁?

4.延时执行,异步执行。

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(sec * NSEC_PER_SEC)), 
  dispatch_get_main_queue(), ^{           });

参数1:时间,dispatch_time(DISPATCH_TIME_NOW, (int64_t)(sec * NSEC_PER_SEC)
DISPATCH_TIME_NOW:从当前时间开始计算经过多少纳秒后执行。
NSEC_PER_SEC:1秒等于多少纳秒。
参数2:队列。
参数3:任务block。

5.在app生命周期内只执行一次,线程安全,比互斥锁效率高。onceToken必须使用全局的,否则在多线程中不安全。

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{    });    

6.dispatch_group_t,调度组,在多个任务都完成后再执行某个任务。

    dispatch_group_t group = dispatch_group_create();
    "新任务开始,每一个任务开始必须匹配一个结束,不然notify一直等待。"
    dispatch_group_enter(group);
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
        NSLog(@"任务1");
        dispatch_group_leave(group);//新任务结束
    });
    
    dispatch_group_enter(group);
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
        NSLog(@"任务2");
        dispatch_group_leave(group);
    });
    "所有通过同一个group开启的任务都结束后再执行的任务。"
    dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
        
        NSLog(@"任务3");
    });
    "等待任务1和任务2都完成再往下执行,不用等待任务3"
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"123");

7.栅栏函数。
dispatch_barrier_async,分割队列中的异步任务,栅栏之前的所有异步任务执行完后再执行栅栏之后的异步任务。
dispatch_barrier_sync,分割所有任务(包括主队列中的任务),不能直接在主队列使用会造成死锁。
问:在dispatch_get_global_queue(0, 0)中两个函数都不起作用,why???

    dispatch_queue_t q = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(q, ^{
        sleep(2);
        NSLog(@"任务1");
    });
    NSLog(@"任务2");
    
    dispatch_barrier_async(q, ^{
        sleep(1);
        NSLog(@"barrier");
    });
    
    NSLog(@"任务3");
    dispatch_async(q, ^{
        NSLog(@"任务4");
    });

8.dispatch_apply。
循环执行某个任务,如果是并发队列异步执行,串行队列同步执行。函数本身为同步函数,要防死锁,不能在主队列执行。

! dispatch_apply函数说明
        *
        *  @brief  dispatch_apply函数是dispatch_sync函数和Dispatch Group的关联API
        *         该函数按指定的次数将指定的Block追加到指定的Dispatch Queue中,并等到全部的处理执行结束
        *
        *  @param 10    指定重复次数  指定10次
        *  @param queue 追加对象的Dispatch Queue
        *  @param index 带有参数的Block, index的作用是为了按执行的顺序区分各个Block
        *
        */

9.dispatch_semaphore_create & dispatch_semaphore_signal & dispatch_semaphore_wait


  "创建信号量,并设置信号量数量,即最大并发数。
  dispatch_semaphore_t t = dispatch_semaphore_create(0);
  第二个参数 timeOut:超时时间,超时直接信号量+1,任务依然会执行完毕。类型为dispatch_time_t,系统定义
     DISPATCH_TIME_NOW  表示当前
    DISPATCH_TIME_FOREVER  表示遥远的未来
   也可以通过 dispatch_time 和 dispatch_walltime 来自定义时间。"
  dispatch_queue_t q = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);

  dispatch_time_t duration = dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC); 
  "超时10秒,设置后如果此处信号量为0则在此处等待10秒后再往下执行,注意设置超时必须是在此处信号量(-1之前)为0时才能生效。
 wait使信号量-1,信号量为0时后面的任务(即下一个wait之后的所有任务)进入等待状态,只有获取到信号量或者等待超时才能继续执行。"
  dispatch_semaphore_wait(t, duration);
  dispatch_async(q, ^{
      sleep(1);
      NSLog(@"任务1");
      "信号量+1"
      dispatch_semaphore_signal(t);
  });
  NSLog(@"任务2");

  "此时等待任务4也不会执行,即等待的是后面包括主线在内的所有任务,需要任务1释放信号量后再执行后面任务"
  dispatch_semaphore_wait(t, DISPATCH_TIME_FOREVER);
  dispatch_async(q, ^{
      sleep(2);
      NSLog(@"任务3");
      dispatch_semaphore_signal(t);
  });
  NSLog(@"任务4");

  dispatch_semaphore_wait(t, DISPATCH_TIME_FOREVER);
  dispatch_async(q, ^{
      sleep(1);
      NSLog(@"任务5");
      dispatch_semaphore_signal(t);
  });
  NSLog(@"任务6");

执行顺序:
2018-07-09 15:22:36.152 ios_GCD[1341:508652] 任务2
2018-07-09 15:22:47.157 ios_GCD[1341:508707] 任务1
2018-07-09 15:22:47.158 ios_GCD[1341:508652] 任务4
2018-07-09 15:22:49.164 ios_GCD[1341:508707] 任务3
2018-07-09 15:22:49.164 ios_GCD[1341:508652] 任务6
2018-07-09 15:22:50.173 ios_GCD[1341:508707] 任务5

你可能感兴趣的:(iOS多线程笔记2--GCD)