第六章:块(block)与大中枢派发(GCD)

块(block)的内部结构:

第六章:块(block)与大中枢派发(GCD)_第1张图片
43BBDFA9-9F5E-488A-9808-A723854DDE5B.png

Invoke-> 函数指针,函数原型至少要接收一个void*型的参数,此参数代表块,块其实就是一种代替函数指针的语法结构

descriptor变量是指向结构体的指针,每个块里都包含此结构体,声明了块的整体大小,还声明了copy和dispose这两个函数对应的指针函数

块还会把所捕获的所有变量都拷贝一份(拷贝指针变量)

  • 技巧二十六:块的使用注意

1.块只在定义它的那个范围内{ }有效,如果需要出了作用域仍旧可以使用,那么需要copy,将块从栈拷贝到堆

2.除了“栈块”和“堆块”外,还有全局块,全局块在编译期就已经完全确定,不会捕捉任何状态,运行时也不会有状态来参与

3.用typedef给块起别名,根据功能的不同,相同的参数的块也应该起不同的别名

  • 技巧二十七:用handle块降低代码的分散程度

1.创建对象的时候可以用内联的handle块将部分业务逻辑连接在一块

2.可以由API设计者指定线程

  • 技巧二十八:多用派发队列,少用同步锁

情景:多个线程要执行同一份代码

1.在GCD出现以前用的同步锁(不推荐,影响性能)

    @synchronized (self) {        
      //doSomeThing    
    }    

2.NSLock(可以,但是可能会出现死锁)

    NSLock *lock = [[NSLock alloc]init];   
    [lock lock];    
    //doSomeThing   
    [lock unlock];

3.NSRecursiveLock(递归锁)(可以,但是可能会出现死锁)

4.GCD(同步串行)(推荐)

  • 技巧二十九:少用perforselect,多用GCD

1.动态执行选择子,在内存管理上有疏失,ARC编译器不能在适当的地方插入内存管理方法

  1. 参数(最多两个)和返回值有限制(返回值必须为对象)
  • 技巧三十: 掌握GCD及操作队列的使用时机

使用NSOperationQueue相对GCD的优势

1.取消队列,GCD的模式类似“安排好任务以后就不管了”(fire and forget),GCD中如果真要取消要写应用层代码,而操作队列已经帮我们写好了cancel,不过已经启动的任务无法取消

2.设置依赖关系

3.通过KVC观察可以更为精细的控制对象所要执行的任务(isFinish、isCancel)

4.操作的优先级 优于 线程的优先级

5.对象可以携带信息自定义方法,在代码中多次使用,符合软件开发中不重复原则(DRY)

  • 技巧三十一: 通过调度组机制,根据系统资源状况来执行任务

GCD调度组(dispatch group)其中最重要,最值得注意的用法就是: 将要并发执行的多个队列合并成一组,于是调用者就能知道何时这些任务才能全部执行完毕

// 队列(决定任务是否需要互相等待执行)跟线程没有必然联系,队列决定了任务的执行方式,线程是任务的执行通道

将队列添加到调度组
dispatch_group_async(group, queue,block)

监听调度组内的任务执行完毕
dispatch_group_notify(group, queue,block)
  • 技巧三十二: 通过dispatch_once,创建线程安全的单例
+(instancetype)sharedInstance{    

      static People *sharedInstance = nil;    
      static dispatch_once_t onceToken;   
      dispatch_once(&onceToken, ^{        
        sharedInstance = [[People alloc]init];    
      });   
      return sharedInstance;
}

你可能感兴趣的:(第六章:块(block)与大中枢派发(GCD))