GCD提供和管理FIFO队列,应用程序可以在块对象的形式提交的任务。提交给调度队列的块在系统完全由系统管理的线程池上执行。对执行任务执行的线程没有保证。GCD提供三种队列:
主要任务:任务在应用程序的主线程上连续执行
并行:工作队按照先进先出的顺序,但同时运行,可以以任何顺序完成。
串行:任务执行一个在先进先出的顺序一次
并发队列同时执行大量的任务。GCD自动创建四个并发调度队列(三之前的iOS 5和OS X v10.7)是全局应用程序,只有它们的优先级区分。您的应用程序请求这些队列使用dispatch_get_global_queue功能。因为这些并发队列是全局到您的应用程序,您不需要保留和释放它们,保留和释放对它们的调用都将被忽略。在OS X v10.7或以后或iOS 4.3之后,您还可以创建您自己的代码模块使用额外的并发队列。
使用串行队列,以确保任务在可预测的顺序中执行。这是一个很好的做法,以确定一个特定的目的为每个串行队列,如保护一个资源或同步关键过程。您的应用程序必须显式创建和管理串行队列。它可以创建尽可能多的他们,但应避免使用它们,而不是并发队列,只是为了同时执行许多任务。
1.异步执行
(1) 为调度队列中的异步执行提交一个块,并立即返回。
void dispatch_async( dispatch_queue_t queue, dispatch_block_t block);
(2)提交一个应用程序定义的函数,用于在调度队列中异步执行,并立即返回。
void dispatch_async_f( dispatch_queue_t queue, void *context, dispatch_function_t work);
2.同步执行
提交一个块对象,用于调度队列的执行,并等待该块完成,意味着当前线程停止。
void dispatch_sync( dispatch_queue_t queue, dispatch_block_t block);
假设,执行 Main Dispatch Queue 时,使用另外的线程 Global Dispatch Queue 进行处理,处理结束后立即使用所得到的结果。在这种情况下使用 dispatch_sync 函数。
dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY,0);
dispatch_sync(queue,^{/** 处理 */});
正因为 dispatch_sync 函数使用简单,所以也容易引起死锁问题。
所谓死锁: 是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
例如,如果在主线程执行以下源代码就会死锁。
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue,^{NSLog(@"Hello?");});
3.将用于在指定的时间执行块。
void dispatch_after( dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block);
在3s 后将指定的 Block 追加到 Main Dispatch Queue 中的源代码如下:
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,3ull*NSEC_PER_SEC);
dispatch_after(time,dispatch_get_main_queue(),^(
NSLog(@"waited at least three seconds");
));
第一个参数用 dispatch_time 函数或 dispatch_walltime 函数生成。dispatch_time 函数通常用于计算相对时间,而 dispatch_walltime 函数用于计算绝对时间。
需要注意的是,dispatch_after 函数并不是在指定时间后执行处理,而只是在指定时间内追加处理到 Dispatch Queue。此源代码和在3s 后用 dispatch_async 函数追加 Block 到 Main Dispatch Queue 的相同。
4.提交一个块为多个调用调度队列。
void dispatch_apply( size_t iterations, dispatch_queue_t queue, void (^block)( size_t));
dispatch_apply 函数是 dispatch_sync 函数和 Dispatch Group 的关联 API。该函数按指定的次数将指定的 Block 追加到指定的 Dispatch Queue 中,并等待全部处理执行结束。
第一个参数为重复次数,第二个参数为追加对象的 Dispatch Queue,第三个参数为追加的处 理。例如要对 NSArray 类对象的所有元素执行某些处理时,不必编写 for 循环部分。
dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_apply([array count],queue,^(size_t index){
NSLog(@"%zu:%@",index,[array objectAtIndex:index]);
});
另外,由于 dispatch_apply 函数也与 dispatch_sync 函数相同,会等待处理执行结束,因此推荐在 dispatch_async 函数中非同步地执行 dispatch_apply 函数。
dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
/**在 Global Dispatch Queue 中非同步执行 */
dispatch_async(queue,^{
/**Global Dispatch Queue, 等待dispatch_apply 全部处理执行结束*/
dispatch_apply([array count],queue,^(size_t index){
/** 并行处理包含在 NSArray 对象的全部对象 */
NSLog(@"%zu:%@",index,[array objectAtIndex:index]);
});
/** dispatch_apply 函数中的处理全部执行结束 */
/** 在 Main Dispatch Queue 中非同步执行 */
dispatch_asycn(dispatch_get_main_queue(),^{
/** 在 Main Dispatch Queue 中执行处理用户更新界面等 */
NSLog(@"done");
});
});
5.在整个应用程序周期内只执行一次。
void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);
dispatch_once 函数是保证在应用程序执行中只执行一次指定处理的 API。
static dispatch_once_t pred;
dispatch_once(&pred,^{
/**初始化 */
});
通过 dispatch_once 函数可以使得在多线程环境下执行,也可以保证安全。也就是所说的单例模式,在生成单例对象时使用。
网友评论