[ios]GCD-Grand Central Dispatch - 二

[ios]GCD-Grand Central Dispatch - 2

Grand Central Dispatch =GDC

1.有两种,顺序的serial Dispatch Queue 与 并发的Concurrent Dispatch Queue
     前者是所有加入这个queue的block会顺序执行,完成一个在开始第二个。既此队列只开一个线程顺序执行。
     后者是所有加入这个queue的block会并发执行,第二个的开始与第一个是否结束无关,他会选择最有解决线程创建方案,不会每个block创建一个线程(比如b1,b2,b3当要执行b3的时候,b1执行完了,此时b3会加入b1的线程而不会重新创建)。

2.创建方式
     dispatch_queue_t xxx = dispatch_queue_create("queueName",Null) //这个是创建了serial Dispatch Queue
     dispatch_queue_t xxx = dispatch_queue_create("queueName",DISPATCH_QUEUE_CONCURRENT);//这个是创建concurrent dispatch queue
需要人工release

3.Main Dispatch Queue/Global Dispatch Queue
   Main Dispatch Queue 主线程队列 加入次线程的都会在主线程进行执行,既丢入NSRunLoop里。一般需要刷新页面相关的才会使用。
   Global Dispatch Queue 是做一个快速获取的Concurrent dispatch queue存在的,他有4个优先级 background,low,default,high
注意:使用MainDQ 和 GlobalDQ 是不需要进行retain 或release的 

4.dispatch_set_target_queue
     设置队列优先级。
dispatch_set_target_queue(Q1,Q2);
Q1为需要修改优先级的,Q2为Q1要与他同级的。
MainDQ 与GlobalDQ因为是全局 所以无法作为第一个参数。
     在必须将不可并行的处理追加到多个serial Dispatch Queue 中时,如果使用dispatch_set_target_queue函数将目标指定为某一个serialDispatchQueue即可防止处理并行执行。

5.dispatch_after 与 dispatch_walltime
     dispatch_after 为延迟多久加入队列(相对时间)
     dispatch_walltime 为在什么时间加入队列(绝对时间)
ex:
     dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,3ull * NSEC_PER_SEC);
     dispatch_after(time,dispatch_get_main_queue(),^{…});
     dispatch_time_t 是从第一个参数的时间开始,经历第二个参数的市场之后。
     ull 是C语言数值字面量
     NSEC_PER_SEC为秒为计数单位
     NSEC_PER_MSEC为毫秒的计数单位
     dispatch_walltime 返回的为dispatch_time_t 书p155

*6.Disptach Group
将dispatch 加入group,并且设置执行group队列完后的执行代码。
     ex:
     dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_DEFAULT,0);
dispatch_group_t group=disptach_group_create();
dispatch_group_async(group,queue,^{1...});
dispatch_group_async(group,queue,^{2...});
dispatch_group_async(group,queue,^{3...});
dispatch_group_notify(group,dispatch_get_main_queue(),^{结束后执行的});
dispatch_release(group);

注意:在dispatch_group_notify函数中不管指定怎么样的Dispatch Queue,属于Dispatch Group的处理在追加的block(上面例子的【结束后执行的】)时都已经结束。

另外还有dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
这个表示 调用他的线程永远等待(因为第二个参数DISPATCH_TIME_FOREVER,如果是其他ex:disptach_time_t time=dispatch_time(DISPATCH_TIME_NOW,1ull*NSEC_PER_SEC);
dispatch_group_wait(group,time);
的话就是等待1秒) 
long result=dispatch_group_wait(……);
返回值为long型
if(result==0){
    // 等待时间结束后,group的全部处理执行结束
}else{
    // 等待时间结束后,group的还有未完成的处理
}

正常情况下不适用dispatch_group_wait,而使用dispatch_group_notify(group,dispatch_get_main_queue(),^{结束后执行的});
可以更好的简化代码。

7.dispatch_barrier_async
     为了规避Concurrent dispatch queue使用中的并发读取数据,数据竞争等问题。
使用dispatch_barrier_async
ex:
     queue 为Concurrent dispatch queue
     queue 其他处理1
     queue 其他处理2
     dispatch_barrier_async(queue,blk_for_writing)
     queue 其他处理3
     queue 其他处理4
     其他处理1 2 执行完 才会执行dispatch_barrier_async,dispatch_barrier_async执行完才会执行 其他处理 3 4
     如果其他处理都是数据库读操作  dispatch_barrier_async是数据库写操作,那么这样能保证 3 4 读取的数据是修改(写入)后的,数据保持正确。

8.dispatch_sync
     同步执行,与dispatch_async相反。此方法不能将block加到,mainQueue中,会导致死锁。也不能给Serial Dispatch Queue增加block,也会导致死锁。
     简单的说这个一般不用,用只用在Concurrent dispatch queue中。(其实一般不会用到)

9.dispatch_apply
     重复执行block,x次。
ex:     dispatch(10,queue,^{…block…});
          NSlog(@“done");
     重复执行block 10次,并且等待执行结束后才继续执行NSlog(@“done”)。
注意:dispatch_apply([array count],queue,^(size_t index){…block…});
     size_t index代表数组下标,上面代码会将数组array的每个下表都丢入block中执行一次。

10.dispatch_suspend/dispatch_resume
    dispatch_suspend 挂起已经追加的处理(未执行的处理暂不执行)
    dispatch_resume 恢复已经追加的处理

11.Dispatch Semaphore 
     代码性排他,通过计数器来限制当前代码在执行过程中只能有限的线程数执行。
创建:dispatch_semaphore_t semaphore=dispatch_semaphore_create(1);
创建一个dispatch_semaphore_t 并且初始化计数为1;

等待(此代码后开始限制线程(排他),加锁,并且计数-1)。
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);

排他控制结束(解锁,并且计数+1)
disptach_semaphore_signal(semaphore);

12.Dispatch_once
     保证在应用程序执行过程中只执行一次的指令。
     static dispatch_once_t pred;s
dispatch_once(&pred, ^{……});

13.Dispatch I/O
     通过使用Dispatch I/O可以并发读写数据,提高效率 p167

14.dispatch_queue 与 dispatch_source
     是无法中断的,要么使用内部标志位。
     而dispatch_source 并且可以设置回调的cancel block。