GCD5: 用GCD同步执行非UI相关的任务
讨论:
当执行那些与 UI 无关的任务,或者与 UI 交互的任务时,和执行其他任务一样,会需要大量时间,以上情况会经常出现。例如,你想下载一个图片并想在下载完成之后展现给用户。下载过程却和 UI 没有任何关系。
对于任何与 UI 无关的任务,你可以使用 GCD 中的全局并发队列。它们允许同步和异步执行。
如果你同步提交一个任务到一个并发队列,同时提交另一个同步任务到另一个并发队列;相对而言这两个同步任务将异步运行,因为他们运行在两个不同的并发队列上。理解这一点很重要,正如我们将看到的那样,你想确定在 B 任务开始之前 A 任务完成了。为了保证这一点,把它们同时提交一个相同的队列。
下面我们看个例子:
它输出整数 1 到 1000 两次,一个完整的序列紧跟着另一个,但是并不会阻止主线。我们可以创建一个为我们计数的Block并且把同一个Block调用两次:
void(^printFrom1To100)(void) = ^{ NSUInteger counter = 0; for(counter = 1;counter <= 100;counter++){ NSLog(@"Counter = %lu - Thread = %@", (unsigned long)counter, [NSThread currentThread]); } };
现在我们用 GCD 来调用这个 Block :
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //priority 优先级 dispatch_sync(concurrentQueue, printFrom1To100); dispatch_sync(concurrentQueue, printFrom1To100);
运行这段代码,你会发现计数发生在主线程,即使你已经要求过并发队列执行这个任务。
为什么呢?:这是 GCD 的优化。 作为一个优化,这个函数调在可能的情况下在当前线程上调用了Block。
执行时为了在一个分派队列上用 C 函数来同步代替 Block Object,使用 dispatch_sync_f function:
void printFrom1To1002(void *paramContext){ NSUInteger counter = 0; for(counter = 1;counter <= 100;counter++){ NSLog(@"Counter = %lu - Thread = %@", (unsigned long)counter, [NSThread currentThread]); } } //调用 dispatch_sync_f(concurrentQueue, NULL, printFrom1To1002);
Dispatch_get_global_queue 函数的第一个参数说明了并发队列的优先级,这个属性 GCD 必须替程序员检索。优先级越高,将提供更多的 CPU Timeslice 来获取该队列执行的代码。
你可以使用下面这些值作为 Dispatch_get_global_queue 函数的第一个参数:
DISPATCH_QUEUE_PRIORITY_LOW 您的任务比正常任务用到更少的时间片。
DISPATCH_QUEUE_PRIORITY_DEFAULT 执行代码的默认系统优先级将应用于您的任务。
DISPATCH_QUEUE_PRIORITY_HIGH 和正常任务相比,更多的时间片会应用到你的任务中。
Dispatch_get_global_queue 函数的第二个参数是预留的,你只要一直给它输入数值 0 就可以了。