- 同步
- 异步
- 并行
- 串行
- 任务组
- 时间等待
Dispatch Queue有两种:数据库
- 1.Serial Dispatch Queue,串行Queue,按队列顺序每次只能执行一个该线程中追加的任务(可经过建立多个串行queue实现并行执行任务(会下降性能))
- 串行queue可解决多个线程更新相同资源致使数据竞争的问题,让操做该资源的任务放在同一个串行queue中执行便可
- 2.Concurrent Dispatch Queue,并行Queue,该线程中追加的任务可同时执行
获取Dispatch Queue(dispatch_queue_t类型)对象有两种方法:多线程
- 1.经过C函数dispatch_queue_create("queueName",NULL);
- 当第二个参数为NULL时,建立的queue为串行queue
- 当第二个参数为DISPATCH_QUEUE_CONCURRENT宏时,建立的queue为并行queue
- dispatch_queue_carete(或其余GCD API中包含create的函数生成的对象)生成的queue须要本身调用dispatch_release(dispatch_queue_t变量)释放
- dispatch_async(queue变量,^{往queue中追加的任务体block})函数会让block持有该queue,因此能够在该函数后即时调用dispatch_release(queue变量)函数释放queue,block执行完后ARC会主动调用dispatch_release(queue变量)函数释放queue,
- dispatch_retain函数可以让变量持有queue
- 2.经过获取系统标准提供的Main Dispatch Queue(主线程,串行)或Global Dispatch Queue(并行,有4个执行优先级:高DISPATCH_QUEUE_PRIORITY_HIGH,默认DISPATCH_QUEUE_PRIORITY_DEFAULT,低DISPATCH_QUEUE_PRIORITY_LOW,后台DISPATCH_QUEUE_PRIORITY_BACKGROUND)
- 获取Main Dispatch Queue如:dispatch_queue_t mainDispatchQueue=dispatch_get_main_queue();
- 获取Global Dispatch Queue如:dispatch_queue_t globalDispatchQueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0);
- 第一个参数为指定该queue的执行优先级
变动由dispatch_queue_create函数生成的dispatch_queue_t对象的执行优先级的方法:并发
- 经过调用dispatch_set_target_queue(需变动的queue对象变量,要变动成该queue同样优先级的queue对象变量)函数
- 众queue中,只有Global Dispatch Queue能够在获取时直接指定优先级,因此dispatch_set_target_queue函数第二个参数能够以Global Dispatch Queue对象变量做为入参去变动第一个参数的queue执行优先级
限制Dispatch Queue的执行阶层的方法:app
- 也是经过调用dispatch_set_target_queue(通常是限制串行目标queue1,在限制对象为串行queue2)函数
想在指定时间后把block体任务追加到线程中(指定时间执行任务,也不必定绝对是指定时间后就执行该任务,由于只是指定时间后把任务加到线程中,可能线程还有别的事情作而延迟)的方法:异步
- 经过调用dispatch_after(dispatch_time_t对象变量,dispatch_queue_t对象变量,^{追加的任务block体})函数
- 第一个参数经过dispatch_time(开始时间如DISPATCH_TIME_NOW,延迟多长时间如3ull*NSEC_PER_SEC)函数获取dispatch_time_t对象
- dispatch_time(,)函数一般用户计算相对时间,还有一个dispatch_walltime()函数用于获取绝对时间(略)
想在多个处理(使用并行queue或同时执行多个串行queue时)所有结束后(在未所有执行结束前不会让调用执行的线程挂起等待)执行指定操做的方法(可用于任务间的依赖关系): async
- 经过Dispatch Group任务组来追加管理众任务,具体作法:
- 1.往线程追加block体任务时指定该任务所属任务组(各任务block体所追加到的线程不必定须要在同一条线程中,可是须要是同一个任务组中),经过调用dispatch_group_async(dispatch_grooup_t对象变量,任务追加到的执行的线程queue,^{block任务体})函数屡次调用屡次追加任务到任务组中
- 第一个参数经过dispatch_group_create()函数获取dispatch_group_t对象
- 2.而后经过调用dispatch_group_notify(dispatch_grooup_t对象变量,结束任务执行的线程queue不必定是和任务组中的其余任务线程同样,^{block任务体})函数追加任务组中所有任务执行完后的任务
- 3.最后要释放由dispatch_group_create()函数获取dispatch_group_t对象,经过调用dispatch_release(dispatch_group_t对象变量)释放
想等待任务组中各任务所有任务执行完毕的方法(在未所有执行结束前会让调用执行的线程挂起等待)
经过Dispatch Group任务组来追加管理众任务,具体作法:函数
- 1.往线程追加block体任务时指定该任务所属任务组,经过调用dispatch_group_async(dispatch_grooup_t对象变量,任务追加到的执行的线程queue,^{block任务体})函数屡次调用屡次追加任务到任务组中
- 第一个参数经过dispatch_group_create()函数获取dispatch_group_t对象
- 2.而后经过调用dispatch_group_wait(dispatch_grooup_t对象变量,dispatch_time_t对象变量等待时间或宏DISPATCH_TIME_FOREVER永远等)函数等待任务组中任务执行完毕(中途不能取消)
- dispatch_group_wait(,)函数返回值==0表明等待时间内任务组中的任务所有执行完毕,否则就是超过等待的时间后任务组中的某一个处理还在执行中
- 调用dispatch_group_wait(,)函数的线程会在调用dispatch_group_wait(,)后便开始中止,通过等待时间后或任务组中任务所有执行完毕后才继续往下执行
- 3.最后要释放由dispatch_group_create()函数获取dispatch_group_t对象,经过调用dispatch_release(dispatch_group_t对象变量)释放
想读取文件或操做数据库时更高效率不单止全部操做仅交给一条串行线程负责,而是全部读写操做并行执行,写入操做保证在任一个读取处理没有执行状态下执行,而且执行写入操做未结束前读取操做不可执行,高效有效处理资源竞争问题:性能
- 经过调用dispatch_barrier_async/dispatch_barrier_sync函数结合dispatch_queue_create函数生成的并行queue一块儿使用实现,栏栅追加也就是dispatch_barrier_async/dispatch_barrier_sync只针对并行queue使用,具体作法:
- 1.dispatch_queue_create(,)函数生成并行queue
- 2.须要读取时调用dispatch_async(并行queue,^{读取任务block体})往并行queue中追加读取操做
- 3.在须要写入操做时,调用dispatch_barrier_async/dispatch_barrier_sync(与读取操做同一条并行queue,^{写入任务block体})函数
- 4.须要读取时调用dispatch_async(并行queue,^{读取任务block体})往并行queue中追加读取操做
- (原理:并行队列若是发现接下来要处理的任务block体是由栏栅方式追加的,那么就一直等当前这并发线程中已经正在并发执行着的任务块都执行完,才单独执行这个栏栅任务block体,等这个栏栅块执行完后才再去并发执行该并发线程中剩余的任务体)
想按指定的次数将指定的任务block体追加到指定的dispatch_queue_t(并行或串行的queue均可以)中,并等待所有处理执行结束的方法:spa
- 经过调用dispatch_apply(指定的追加次数,指定的并行线程,^(size_t index){指定的任务block体})函数实现
- 当执行调用该函数的线程调用了该函数后,将会等待这批次的任务体执行完才往下执行。所以调用该函数的线程一半为子线程而且是在异步追加到该子线程的任务block体中调用
- 不在子线程调用会卡界面,不是在异步追加的任务block体中调用的话会致使死锁
当线程执行大量操做想挂起线程或者恢复线程的方法:线程
- 经过调用dispatch_suspend(dispatch_queue_t对象变量)函数可挂起指定的线程
- 经过调用dispatch_resume(dispatch_queue_t对象变量)函数可恢复指定线程继续执行任务
想保证在引用程序执行期间只执行一次指定处理的方法:
- 经过调用dispatch_once(&dispatch_once_t对象变量,^{指定处理的block体})函数实现
- 其中第一个参数dispatch_once_t对象变量须要是静态的,如直接static dispatch_once_t token;把&token传入第一个参数便可
- 一般用于建立单例类,以下语法:
- +(id)sharedInstance{
- static MyObject *myObjectManager=nil;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken,^{
- myObjectManager=[[self alloc]init];
- });
- return myObjectManager;
- }
想进行更细粒度的排他控制的方法:
- 经过Dispathc Semaphore处理(略)
想提升文件读取速度的方法:
往Dispatch Queue追加任务有两种方式:
- 1.异步追加,调用C函数dispatch_async(dispatch_queue_t类型的queue变量,dispatch_block_t类型的block体^{往queue中追加的任务体block})
- 任务追加到的线程不会等待所追加的任务block体执行结束
- 2.同步追加,调用C函数dispatch_sync(dispatch_queue_t类型的queue变量,dispatch_block_t类型的block体^{往queue中追加的任务体block})
- 任务追加到的线程会一直等待所追加的任务block体执行完成,是简易版的dispatch_group_wait函数
- 同步追加容易引发死锁,如往主线程同步追加任务,由于代码执行时,主线程在执行往主线程同步追加任务,因此同步追加的任务主线程永远执行不到,又因是同步追加,因此主线程一直在等待追加的任务执行完毕,
- 致使死锁,亦即不管什么时候,都不能往主线程或主线程执行的任务体中同步追加任务,或者把任务体同步追加到的线程永远不能是调用追加函数也就是调用dispatch_sync(,)函数时的线程及其线程的外部线程(见一下死锁例子)
- 需同步等待例子如:
- 有一条线程好比是主线程执行下面的代码
- NSString *_aString=@"XXXXX";
- -(NSString *)getaString{
- dispatch_queue_t myQueue=dispatch_queue_creat("handleAStringQueue",NULL);
- __block NSString *aString;//为解决多线程竞争使用_aString成员变量,因此对_aString操做都需放handleAStringQueue串行queue中操做,而在queue中不能直接返回_aString成员对象,由于在block中return只是block的返回值,因此须要声明一个替换变量
- dispatch_sync(myQueue,^{aString=_aString});//主线程执行到这里的时候,因为是同步把block任务追加到myQueue中处理执行,因此主线程会挂起直到myQueue线程把追加的block任务体执行完才往下执行
- return aString;//主线程执行到这里的时候因为上面是同步执行,因此block任务体必定已经执行完,因此aString已经被赋值,能够返回出去了。若是上面是异步追加任务的话,那么主线程会把block任务体追加到myQueue中,不等任务体给aString赋值立刻执行return语句,这样是达不到原意的。
- }
- 致使死锁例子如:(表层死锁)
- dispatch_sync(dispatch_get_main_queue(),^{
- NSLog(@"content...");
- });
- 若是以上代码是在主线程运行,就会致使死锁。
- 致使死锁例子如:(深层死锁)
- dispatch_queue_t queueA=dispathc_queue_create("queueA Name",NULL);
- dispatch_queue_t queueB=dispatch_queue_create("queueB Name",NULL);
- //尽管是在另线程调用如下代码:
- dispatch_sync(queueA,^{//在queueA中执行如下代码
- dispatch_sync(queueB,^{//queueA等待queueB执行如下代码
- dispatch_sync(queueA,^{//queueB等待queueA执行如下代码
- NSLog(@"content...");//queueA永远执行不到这里,由于queueA上面同步等待挂起了,因此queueA死锁了
- });
- });
- });