block是什么
block是一个C level的语法以及运行时的一个特性,和标准C中的函数(函数指针)类似。用于回调函数的地方。两个对象间的通讯。实现轻量级的“代理”。
blocks和C语言函数指针的区别
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
// 创建一个串行分发队列
dispatch_queue_t queue = dispatch_queue_create("studyBlocks", NULL);
// 将一个 block 任务加入到其中并行运行. 这样 block 就会在新的线程中运行,直到结束返回主线程
// 加入 dispatch_queue 中的 block 必须是无参数也无返回值的
dispatch_async(queue, ^(void){
int sum = 0;
for (int i = 0; i<100; i++) {
sum += i;
}
NSLog(@"sum:%d",sum);
});
dispatch_release(queue);
[pool drain];
1、dispatch_queue_t 类型 的定义如下:dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[[self captureManager] session] startRunning];
});
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
initData();
// Create a semaphore with 0 resource
__block dispatch_semaphore_t sem = dispatch_semaphore_create(0);
// create dispatch semaphore
dispatch_queue_t queue = dispatch_queue_create("StudyBlocks", NULL); dispatch_async(queue, ^(void) {int sum = 0;
for(int i = 0; i < Length; i++)
sum += data;
NSLog(@" >> Sum: %d", sum);// signal the semaphore: add 1 resource
dispatch_semaphore_signal(sem);});
// wait for the semaphore: wait until resource is ready.
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
dispatch_release(sem);
dispatch_release(queue);
[pool drain];
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
initData();
__block int sum = 0;
// Create a semaphore with 0 resource
__block dispatch_semaphore_t sem = dispatch_semaphore_create(0);
__block dispatch_semaphore_t taskSem = dispatch_semaphore_create(0);
// create dispatch semaphore
dispatch_queue_t queue = dispatch_queue_create("StudyBlocks", NULL);
dispatch_block_t task1 = ^(void) {
int s = 0;
for (int i = 0; i < Length; i++)
s += data;
sum = s;
NSLog(@" >> after add: %d", sum);
dispatch_semaphore_signal(taskSem);
};
dispatch_block_t task2 = ^(void) {
dispatch_semaphore_wait(taskSem, DISPATCH_TIME_FOREVER);
int s = sum;
for (int i = 0; i < Length; i++)
s -= data;
sum = s;
NSLog(@" >> after subtract: %d", sum);
dispatch_semaphore_signal(sem);
};
dispatch_async(queue, task1);
dispatch_async(queue, task2);
// wait for the semaphore: wait until resource is ready.
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
dispatch_release(taskSem);
dispatch_release(sem);
dispatch_release(queue);
[pool drain];
在上面的代码中,我们利用了 dispatch_queue 的 FIFO 特性,确保 task1 先于 task2 执行,而 task2 必须等待直到 task1 执行完毕才开始干正事,主线程又必须等待 task2 才能干正事。 这样我们就可以保证先求和,再相减,然后再让主线程运行结束这个顺序。
使用 dispatch_apply 进行并发迭代:
对于上面的求和操作,我们也可以使用 dispatch_apply 来简化代码的编写.
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
initData();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
__block int sum = 0;
__block int *pArray = data;
// iterations
//
dispatch_apply(Length, queue, ^(size_t i) {
sum += pArray;
});
NSLog(@" >> sum: %d", sum);
dispatch_release(queue);
[pool drain];
dispatch group
我们可以将完成一组相关任务的 block 添加到一个 dispatch group 中去,这样可以在 group 中所有 block 任务都完成之后,再做其他事情。比如 6 中的示例也可以使用 dispatch group 实现:
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
initData();
__block int sum = 0;
// Create a semaphore with 0 resource
//
__block dispatch_semaphore_t taskSem = dispatch_semaphore_create(0);
// create dispatch semaphore
//
dispatch_queue_t queue = dispatch_queue_create("StudyBlocks", NULL);
dispatch_group_t group = dispatch_group_create();
dispatch_block_t task1 = ^(void) {
int s = 0;
for (int i = 0; i < Length; i++)
s += data;
sum = s;
NSLog(@" >> after add: %d", sum);
dispatch_semaphore_signal(taskSem);
};
dispatch_block_t task2 = ^(void) {
dispatch_semaphore_wait(taskSem, DISPATCH_TIME_FOREVER);
int s = sum;
for (int i = 0; i < Length; i++)
s -= data;
sum = s;
NSLog(@" >> after subtract: %d", sum);
};
// Fork
dispatch_group_async(group, queue, task1);
dispatch_group_async(group, queue, task2);
// Join
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(taskSem);
dispatch_release(queue);
dispatch_release(group);
[pool drain];
在上面的代码中,我们使用 dispatch_group_create 创建一个 dispatch_group_t,然后使用语句:dispatch_group_async(group, queue, task1)将 block 任务加入队列中,并与组关联,这样我们就可以使用 dispatch_group_wait(group, DISPATCH_TIME_FOREVER)来等待组中所有的 block 任务完成再继续执行。
至此我们了解了 dispatch queue 以及 block 并行编程相关基本知识,开始在项目中运用它们吧。