void dispatch_apply(size_t iterations, dispatch_queue_t queue, void (^block)(size_t)); //重复执行block,需要注意的是这个方法是同步返回,也就是说等到所有block执行完毕才返回,如需异步返回则嵌套在dispatch_async中来使用。多个block的运行是否并发或串行执行也依赖queue的是否并发或串行。 void dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block); //这个函数可以设置同步执行的block,它会等到在它加入队列之前的block执行完毕后,才开始执行。在它之后加入队列的block,则等到这个block执行完毕后才开始执行。 void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block); //同上,除了它是同步返回函数 void dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block); //延迟执行block 最后再来看看dispatch队列的一个很有特色的函数: void dispatch_set_target_queue(dispatch_object_t object, dispatch_queue_t queue); 它会把需要执行的任务对象指定到不同的队列中去处理,这个任务对象可以是dispatch队列,也可以是dispatch源(以后博文会介绍)。而且这个过程可以是动态的,可以实现队列的动态调度管理等等。比如说有两个队列dispatchA和dispatchB,这时把dispatchA指派到dispatchB: dispatch_set_target_queue(dispatchA, dispatchB); 那么dispatchA上还未运行的block会在dispatchB上运行。这时如果暂停dispatchA运行: dispatch_suspend(dispatchA); 则只会暂停dispatchA上原来的block的执行,dispatchB的block则不受影响。而如果暂停dispatchB的运行,则会暂停dispatchA的运行。 这里只简单举个例子,说明dispatch队列运行的灵活性,在实际应用中你会逐步发掘出它的潜力。 dispatch队列不支持cancel(取消),没有实现dispatch_cancel()函数,不像NSOperationQueue,不得不说这是个小小的缺憾。 iOS多线程的初步研究(十)-- dispatch同步GCD提供两种方式支持dispatch队列同步,即dispatch组和信号量。 一、dispatch组(dispatch group) 1. 创建dispatch组 dispatch_group_t group = dispatch_group_create(); 2. 启动dispatch队列中的block关联到group中 dispatch_group_async(group, queue, ^{ // 。。。 }); 3. 等待group关联的block执行完毕,也可以设置超时参数 dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 4. 为group设置通知一个block,当group关联的block执行完毕后,就调用这个block。类似dispatch_barrier_async。 dispatch_group_notify(group, queue, ^{ // 。。。 }); 5. 手动管理group关联的block的运行状态(或计数),进入和退出group次数必须匹配 dispatch_group_enter(group); dispatch_group_leave(group); 所以下面的两种调用其实是等价的, A) dispatch_group_async(group, queue, ^{ // 。。。 }); B) dispatch_group_enter(group); dispatch_async(queue, ^{ //。。。 dispatch_group_leave(group); }); 所以,可以利用dispatch_group_enter、 dispatch_group_leave和dispatch_group_wait来实现同步,具体例子:#10644282。 二、dispatch信号量(dispatch semaphore) 1. 创建信号量,可以设置信号量的资源数。0表示没有资源,调用dispatch_semaphore_wait会立即等待。 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); 2. 等待信号,可以设置超时参数。该函数返回0表示得到通知,非0表示超时。 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 3. 通知信号,如果等待线程被唤醒则返回非0,否则返回0。 dispatch_semaphore_signal(semaphore); 最后,还是回到生成消费者的例子,使用dispatch信号量是如何实现同步: dispatch_semaphore_t sem = dispatch_semaphore_create(0); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //消费者队列 while (condition) { if (dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, 10*NSEC_PER_SEC))) //等待10秒 continue; //得到数据 } }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //生产者队列 while (condition) { if (!dispatch_semaphore_signal(sem)) { sleep(1); //wait for a while continue; } //通知成功 } }); |