1.什么是GCD
Grand Central Dispatch(GCD)是异步执行任务的技术之一。提供了对底层线程管理的实现。开发者只需要定义想执行的任务并追加到适当的Dispatch Queue中,GCD就会生成必要的线程并计划执行任务。dispatch_async(queue,^ { /* *执行任务 */ });
2.Dispatch Queue
Dispatch Queue是执行处理的FIFO(先进先出)等待队列,按照执行处理的方式分为Serial Dispatch Queue和Concurrent Dispatch Queue。Serial Dispatch Queue只使用一个线程来执行处理,要等待现在执行中的处理结束才会执行下一个处理,Concurrent Dispatch Queue采用多个线程来执行处理,不等待现在执行中的处理结束,具体的线程数由iOS和OSX的内核--XNU决定,XUN动态的根据要执行的任务数来增加和减少线程。创建Serial Dispatch Queue
dispatch_queue_t serialDispatchQueue = dispatch_queue_create("SerialDispatchQueueName",NULL); dispatch_async(serialDispatchQueue,^ { }); dispatch_release(serialDispatchQueue);创建Concurrent Dispatch Queue
dispatch_queue_t concurrentDispatchQueue = dispatch_queue_create("ConcurrentDispatchQueueName",DISPATCH_QUEUE_CONCURRENT); dispatch_async(concurrentDispatchQueue,^ { }); dispatch_release(concurrentDispatchQueue);
2.1 Main Dispatch Queue
Main Dispatch Queue是在主线程Runloop中执行处理的Serial Dispatch Queue。dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();
2.2 Global Dispatch Queue
Global Dispatch Queue是Concurrent Dispatch Queue,Global Dispatch Queue有四个执行优先级,分别是高优先级(High Priority)、默认优先级(Default Priority)、低优先级(Low Priority)和后台优先级(Background Priority)。获取方法如下://高优先级 Global Dispatch Queue dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0); //默认优先级 Global Dispatch Queue dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0); //低优先级 Global Dispatch Queue dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0); //后台优先级 Global Dispatch Queue dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);
2.3 常用的Main和Global模型
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^() { //并行处理任务 dispatch_async(dispatch_get_main_queue(),^() { //主线程中执行处理 }); });
3.GCD的API
3.1 dispatch_after
dispatch_after并不是在指定的时候后执行处理,而只是在指定的时间后追加处理到指定的Dispatch Queue,具体执行时间还要看当前线程的执行情况,3秒后追加指定的Block到Main Dispatch Queue中执行:dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,3ull*NSEC_PER_SEC); dispatch_after(time,dispatch_get_main_queue,^() { //3秒后的处理 });
3.2 dispatch_once
dispatch_once函数保证在应用程序的生命周期内只执行一次指定处理的API,单例的实现中常用到。使用方式如下:static dispatch_once_t token; dispatch_once(&token,^() { });
3.3 Dispatch Group
Dispatch Group主要是用于在追加到Dispatch Queue中的多个处理全部处理结束后想执行结束处理的情况,最后想要执行的结束处理的追加可以采用同步(dispatch_group_wait())或者异步(dispatch_group_notify())两种方式。dispatch_group_wait()会阻塞该函数调用的线程,直到添加到Group中的处理全部执行完毕才执行结束处理,而dispatch_group_notify()不会阻塞,会立刻返回,当追加到Group中的所有处理都执行完成的时候,会将指定的Block追加到指定的Dispatch Queue中。具体Dispatch Group使用方式如下:异步:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group,queue,^{ NSLog(@"TestBlock1"); }); dispatch_group_async(group,queue,^{ NSLog(@"TestBlock2"); }); dispatch_group_notify(group,dispatch_get_main_queue(),^{ NSLog(@"Done"); });同步:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group,queue,^{ NSLog(@"TestBlock1"); }); dispatch_group_async(group,queue,^{ NSLog(@"TestBlock2"); }); dispatch_group_wait(group,DISPATCH_TIME_FOREVER); NSLog(@"Done");
3.4 dispatch_sync
dispatch_async是异步的追加Block到指定的Dispatch Queue中,不会阻塞当前函数的线程。而dispatch_sync会阻塞当前函数调用的线程直到追加的Block执行完成。dispatch_sync的功能类似于dispatch_group_wait,阻塞当前线程直到另外一个线程完成了追加的Block的执行,如果当前线程和要处理Block的线程相同,就会造成线程死锁。死锁代码如下:dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue,^ { dispatch_sync(queue,^{ NSLog(@"线程死锁"); }); });
3.5 dispatch_apply
dispatch_apply函数是dispatch_sync函数和Dispatch Group的关联API,该函数按指定次数将指定的Block追加到指定的Dispatch Queue中,并等待全部处理执行结束后返回。dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY,0);
dispatch_apply(10,queue,^(size_t index) { NSLog(@"%zu",index); }); NSLog(@"Done");
3.6 dispatch_barrier_async
dispatch_barrier_async主要是和Concurrent Dispatch Queue结合起来使用,起到线程中栅栏的作用,等待该函数调用之前所有添加到Dispatch Queue中的处理执行完成之后才执行该函数要添加的处理,在该函数添加的处理执行完成后,后续添加到Dispatch Queue的处理才能执行。dispatch_queue_t queue = dispatch_queue_create(@"ConcurrentDispatchQueue",DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue,Block1ForReading); dispatch_async(queue,Block2ForReading); dispatch_async(queue,Block3ForReading); dispatc_barrier_async(queue,BlockForWriting); dispatch_async(queue,Block4ForReading); dispatch_async(queue,Block5ForReading); dispatch_async(queue,Block6ForReading); dispatch_release(queue);
3.7 dispatch_set_target_queue
dispatch_set_target_queue可以用来改变目标Dispatch Queue的优先级为目标Dispatch Queue的优先级。dispatch_queue_t myQueue = dispatch_queue_create(@"myQueue",0); dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0); dispatch_set_target_queue(myQueue,globalQueue);
3.8 dispatch_suspend / dispatch_resume
dispatch_suspend函数挂起指定的Dispatch Queuedispatch_suspend(queue);dispatch_resume会恢复指定的Dispatch Queue
dispatch_resume(queue);
3.9 Dispatch Semaphore
GCD提供了线程的信号量处理函数:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER); dispatch_semaphore_signal(semaphore);