block可用于并行编程,线程同步多用信号量来实现,保证执行完一个block再执行下一个block,当所有block都执行完毕后,再利用group,通知执行后面的代码,使用wait(阻塞线程),或notify(不阻塞线程)等待执行结束后再继续。
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
static volatile BOOL flag = NO;
//一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
static const int Length = 1000000000;
static int Data[Length];
static void initData() {
for (int i = 0; i < Length; i++) {
Data[i] = i+1;
}
}
#define Test_Mode 7
int main(int argc, char * argv[]) {
@autoreleasepool {
#if Test_Mode == 0
//local block
void (^myBlock) (void) = ^(void){
NSLog(@"I am a block");
};
myBlock = ^{
NSLog(@"I have been changed");
};
myBlock();
#elif Test_Mode == 1
//array block
void (^blockArray[2])(void) = {
^{
NSLog(@"block 1");
},
^{
NSLog(@"block 2");
},
};
blockArray[0]();
blockArray[1]();
//block该如何修改外部变量呢?有两种办法,第一种是可以修改 static 全局变量;第二种是可以修改用关键字 __block 修饰的变量。
#elif Test_Mode == 2
//block recursion(递归) (必须用static或__blcok修饰block)
void (^aBlock)(int);
static void (^ const recursionBlock)(int) = ^(int i){
if (i > 0) {
NSLog(@"recursionBlock %d", i);
recursionBlock(i - 1);
}
};
aBlock = recursionBlock;
aBlock(6);
// recursionBlock(5);
__block void (^recursionBlock2)(int) = ^(int i){
if (i > 0) {
NSLog(@"recursionBlock2 %d", i);
recursionBlock2(i - 1);
}
};
aBlock = recursionBlock2;
aBlock(10);
// recursionBlock2(8);
#elif Test_Mode == 3
//dispatch block
initData();//调用初始化函数
void (^dispatchBlcok)(void) = ^{
int sum = 0;
for (int i = 0; i < Length; i++) {
sum += Data[i];
}
NSLog(@"sum = %d", sum);
flag = YES;
};
dispatch_queue_t queue = dispatch_queue_create("dispatch block", 0);
dispatch_async(queue, dispatchBlcok);
while (!flag);//阻塞线程,直到执行完block(非必需)(用信号量实现更好)
#elif Test_Mode == 4
//semaphore(信号量)
initData();
//不用block修饰好像也可以。
__block dispatch_semaphore_t sem = dispatch_semaphore_create(0);//0表示资源未准备好,需要等待
dispatch_queue_t queue = dispatch_queue_create("semaphore block", 0);
dispatch_async(queue, ^{
int sum = 0;
for (int i = 0; i < Length; i++)
sum += Data[i];
NSLog(@"sum = %d", sum);
dispatch_semaphore_signal(sem);//准备好了,增加 semaphore 计数
});
NSLog(@"<<semaphore<<");
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);//可以继续执行了,减少 semaphore 计数
#elif Test_Mode == 5
//多个信号量.按照 FIFO 顺序执行并用 semaphore 线程同步。
initData();
__block int sum = 0;
__block dispatch_semaphore_t sem = dispatch_semaphore_create(0);
__block dispatch_semaphore_t taskSem = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_queue_create("semaphore block", 0);
dispatch_block_t task1 = ^{
int s = 0;
for (int
i = 0; i < Length; i ++) {
s += Data[i];
}
sum = s;
NSLog(@">> sfter add : %d", sum);
dispatch_semaphore_signal(taskSem);
};
dispatch_block_t task2 = ^{
dispatch_semaphore_wait(taskSem, DISPATCH_TIME_FOREVER);
int s = sum;
for (int i = 0; i < Length; i++) {
s -= Data[i];
}
sum = s;
NSLog(@"<< after subtract: %d", sum);
dispatch_semaphore_signal(sem);
};
dispatch_async(queue, task1);
dispatch_async(queue, task2);
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
NSLog(@"after 5");
#elif Test_Mode == 6
//dispatch_apply 进行并发迭代。这么做与 for 循环相比有什么好处呢?答案是:并行,这里的求和是并行的,并不是按照顺序依次执行求和的。
initData();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
__block int sum = 0;
__block int *pArray = Data;
dispatch_apply(Length, queue, ^(size_t i) {
//循环体的执行是并发执行的。
sum += pArray[i];
NSLog(@"pArray :%zu", i);
});
NSLog(@">> sum :%d", sum);
#elif Test_Mode == 7
//<span style="font-family: Arial, Helvetica, sans-serif;">dispatch_queue</span>
initData();
__block int sum = 0;
__block dispatch_semaphore_t taskSem = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_queue_create("group queue", 0);
dispatch_group_t group = dispatch_group_create();
dispatch_block_t task1 = ^{
int s = 0;
for (int i = 0; i < Length; i++) {
s += Data[i];
}
sum = s;
NSLog(@">>after add:%d", sum);
dispatch_semaphore_signal(taskSem);
};
dispatch_block_t task2 = ^{
dispatch_semaphore_wait(taskSem, DISPATCH_TIME_FOREVER);
int s = sum;
for (int i = 0; i < Length; i++) {
s -= Data[i];
}
sum = s;
NSLog(@">> after subtract:%d", sum);
};
dispatch_group_async(group, queue, task1);
dispatch_group_async(group, queue, task2);
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);//保证group里的所有任务执行完后再往下执行。会阻塞当前线程。
NSLog(@"after group wait");
dispatch_group_notify(group, queue, ^{//在group执行完所有任务后执行,具体执行的时间不确定。
NSLog(@"group over");
});
#endif
NSLog(@"<<<<<<Test Done>>>>>>");
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}