您的位置:首页 > 编程语言

写高质量OC代码52建议总结:44.通过Dispatch Group机制,根据系统资源状况来执行任务

2017-07-25 17:19 691 查看
dispatch group能够把任务分组。等待这组任务执行完毕,在回调函数中继续往下执行。比如,可以把压缩一系列文件的任务表示成dispatch group:
dispatch_group_tdispatch_group_create();
 有两种方法给任务编组。
void dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block);
 这个方法是dispatch_async的变体。另一种办法是:
void dispatch_group_enter(dispatch_group_t group);
void dispatch_group_leave(dispatch_group+t group);
 前者可以使分组中正要执行的任务数递增,后者递减。所以,调用了dispatch_group_enter,只有必须对应一个dispatch_group_leave,如果只有enter没有leave,这个任务永远执行不玩。

 这个函数用于等待dispatch group执行完毕:
long dispatch_group_wait(dispatch_group_t group, dispatch_time_t timeout);
 如果执行dispatch group的时间小于timeout,返回0,否则返回非0值。timeout参数也可以取常量DISPATCH_TIME_FOREVER,会一直等dispatch group执行完,不会超时。
void dispatch_group_notify(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block);
 与wait函数略有不同。可以向此函数传入块,等dispatch group函数执行完,块会在特定线程上执行。当当前线程不应阻塞,又想在任务全部完成时得到通知,可以这样做。

 如果想要数组中每个对象都执行某项任务,并且想等待所有任务执行完毕,可以使用GCD这个特性完成。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t dispatchGroup = dispatch_group_create();
for (id object in collection ) {
dispatch_group_async(dispatchGroup, queue, ^{
[object performTask];
});
}
dispatch_group_wait(dispatchGroup, DISPATCH_TIME_FOREVER);
 如果当前线程不应阻塞,可以用notify函数替代wait:
dispatch_queue_t notifyQueue = dispatch_get_main_queue();
idspatch_group_notify(dispatchGroup, notifyQueue, ^{
//  ........
});
 notify回调所选的队列,完全应该根据具体情况定。在本例中,所有任务都派发到同一个任务中,实际上没必要。可以把一部分任务分派到优先级高的线程上。

dispatch_queue_t lowPriorityQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
dispatch_queue_t highPriorityQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_group_t dispatchGroup = dispatch_group_create();

for (id object in lowPriorityObjects) {
dispatch_group_async(dispatchGroup, lowPriorityQueue, ^{
[object performTask];
});
}
for (id object in highPriorityObjects) {
dispatch_group_async(dispatchGroup, highPriorityQueue, ^{
[object performTask];
});
}

dispatch_queue_t notifyQueue = dispatch_get_main_queue();
dispatch_group_notify(dispatchGroup, notifyQueue, ^{
//.........
});
另一种情况,将任务交给各个串行队列中,用dispatch group监控其执行状况。
dispatch_queue_t queue = dispatch_queue_create("com.effectiveobjectec.queue", NULL);

for (id object in collection) {
dispatch_async(queue, ^{
[object performTask];
});
}
dispatch_async(queue, ^{
//......
});
 未必总要使用dispatch group,有时采用单个队列搭配标准的已不派发,实现效果相同。

 为了执行队列中的块,GCD会在适当的时机自动创建新线程或者复用旧线程。通过dispatch group所提供的这种简便方式,可以并发执行一系列给定的任务,又可以在全部任务结束时得到通知。

 

 上面,遍历某个collection,令其每个元素上执行任务,这也可以用另一个GCD来实现:
void dispatch_apply(size_t iterations, dispatch_queue_t queue, void(^block)(size_t));
 此函数会反复执行一定次数,每次给块的参数递增1,从0开始。dispatch_apply所用的队列是并发队列。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(array.cout, queue, ^(size_t i){
id object = array[i];
[object performTask];
});
 这和用dispatch group的效果相同。

 

 总结:

 1.一系列任务可以归纳进dispatch group中,这组任务执行完成时获得回调通知。

 2.用dispatch group,可以在并发队列中同时执行多项任务,GCD会根据系统资源状况来调度这些并发任务。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐