二.先讲一些常用的方法(后面再深层次详解)
1.dispatch_async执行某个代码片段N次。 dispatch_apply(5, globalQ, ^(size_t index) { // 执行5次 });
//以下代码是两种生成Serial Dispatch Queue的方式
dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("cn.edu.scnu.mySerialDispatchQueue", NULL); // dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("cn.edu.scnu.mySerialDispatchQueue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_create,该方法中
//以下代码生成ConcurrentDispatchQueue
dispatch_queue_t myConcurrentDispatchQueue = dispatch_queue_create("cn.edu.scnu.myConcurrentDispatchQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(myConcurrentDispatchQueue, ^{
NSLog(@"block on my ConcurrentDispatchQueue");
});
2、MainDispatch Queue 和 Global Dispatch Queue
//获取Main Dispatch Queue
dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();
GlobalDispatch Queue是所有应用程序都能够使用的Concurrent Dispatch Queue,没有必要通过dispatch_queue_create方法逐个生成Concurrent Dispatch Queue,只要获取GlobalDispatch Queue使用即可。
Global Dispatch Queue有四个优先级:High Priority||Default Priority||Low Priority||Background Priority
//获取高优先级的的Global Dispatch Queue
/*
DISPATCH_QUEUE_PRIORITY_HIGH
DISPATCH_QUEUE_PRIORITY_DEFAULT
DISPATCH_QUEUE_PRIORITY_LOW
DISPATCH_QUEUE_PRIORITY_BACKGROUND
*/
dispatch_queue_t globalDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
//第一个参数指定Global Dispatch Queue的优先级,第二个参数指定为0
dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("cn.edu.scnu.mySerialDispatchQueue", NULL);
dispatch_queue_t globalDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_set_target_queue(mySerialDispatchQueue, globalDispatchQueue);
//指定要变更执行优先级的dispatch queue为dispatch_set_target_queue方法的第一个参数,指定与要使用的执行优先级相同优先级的Global Dispatch Queue为第二个参数(目标)
//第一个参数不可以指定为系统提供的Main Dispatch Queue 和 Global Dispatch Queue
dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("cn.edu.scnu.mySerialDispatchQueue", NULL);
dispatch_queue_t globalDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_set_target_queue(mySerialDispatchQueue, globalDispatchQueue);
//指定要变更执行优先级的dispatch queue为dispatch_set_target_queue方法的第一个参数,指定与要使用的执行优先级相同优先级的Global Dispatch Queue为第二个参数(目标)
//第一个参数不可以指定为系统提供的Main Dispatch Queue 和 Global Dispatch Queue
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
NSLog(@"waited at least 2.0 seconds."); });
值得注意的是,dispatch_after方法并不是在指定时间后执行处理任务,而是在指定时间后追加处理到dispatch queue中,上面的代码在2秒后用dispatch_after方法追加
秒后执行,而且在Main Dispatch Queue中又大量处理追加或者主线程的处理本身有延时时,这个时间会更长。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{NSLog(@"blk1");});
dispatch_group_async(group, queue, ^{NSLog(@"blk2");});
dispatch_group_async(group, queue, ^{NSLog(@"blk3");});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"done"); });
因为向 Global Dispatch Queue即Concurrent Dispatch Queue追加处理任务,多个线程并行执行,所以追加处理任务的执行顺序是不定的,执行时顺序会发生变化,但是主线程中执行结果输出done肯定是最后的。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{NSLog(@"blk1");});
dispatch_group_async(group, queue, ^{NSLog(@"blk2");});
dispatch_group_async(group, queue, ^{NSLog(@"blk3");});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
在这个方法中的第二个参数指定等待时间,这里使用DISPATCH_TIME_FOREVER意味着永久等待,只要属于dispatch group中的处理尚未执行结束,就会一直等待,中途不能取消。
//这里指定等待时间1s,即1s后查看dispatch group中的处理是否全部执行结束
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1ull*NSEC_PER_SEC);
long result = dispatch_group_wait(group, time);
if (result == 0) {
//属于dispatch group中的全部处理都执行结束
}
else {
//属于dispatch group的某一个处理还在执行
}
//这里指定等待时间1s,即1s后查看dispatch group中的处理是否全部执行结束
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1ull*NSEC_PER_SEC);
long result = dispatch_group_wait(group, time);
if (result == 0) {
//属于dispatch group中的全部处理都执行结束
}
else {
//属于dispatch group的某一个处理还在执行 }
//这里也可以指定DISPATCH_TIME_NOW,则不用任何等待即可判断属于dispatch group中的处理是否全部执行结束
long result = dispatch_group_wait(group, DISPATCH_TIME_NOW);
//这里也可以指定DISPATCH_TIME_NOW,则不用任何等待即可判断属于dispatch group中的处理是否全部执行结束
long result = dispatch_group_wait(group, DISPATCH_TIME_NOW);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^{
//表示执行数据读取任务
NSLog(@"blk1_reading");
});
dispatch_async(queue, ^{
NSLog(@"blk2_reading");
});
dispatch_async(queue, ^{
//表示执行数据写入处理任务
NSLog(@"blk1_writting");
});
dispatch_async(queue, ^{
NSLog(@"blk3_reading");
});
dispatch_async(queue, ^{
NSLog(@"blk4_reading");
});
如果像上面那样简单的在dispatch_async方法中添加写入数据处理的任务,那么根据Concurrent Dispatch Queue并行执行的性质,就很有可能不是按照上面的添加处理任务的
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^{
//表示执行数据读取任务
NSLog(@"blk1_reading");
});
dispatch_async(queue, ^{
NSLog(@"blk2_reading");
});
dispatch_barrier_async(queue, ^{
//表示执行数据写入处理任务
NSLog(@"blk1_writting");
});
dispatch_async(queue, ^{
NSLog(@"blk3_reading");
});
dispatch_async(queue, ^{
NSLog(@"blk4_reading");
});
使用dispatch_barrier_async方法,它会等待在它之前添加到 Concurrent Dispatch Queue的所有处理执行结束后,才执行该处理,然后等待该处理结束后,才接着处理后续添
加到Concurrent Dispatch Queue中的处理任务。当然在dispatch_barrier_async方法之前和之后添加的处理任务可以并发执行,即不保证执行顺序,但是可以确保blk1_writting的写入数据任务,然后才是执行接着的读取数据的任务。
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"引起死锁!");
});
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"引起死锁!");
});
上面的代码在主线程中执行指定的block,并等待其执行结束,但是其实在主线程中就是在执行这些代码,所以就造成了死锁。
[cpp]
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10, queue, ^(size_t index){
NSLog(@"%zu",index);
});
NSLog(@"done");
因为是在Global Dispatch Queue中执行处理,所以各个处理的执行时间不定,也就是说输出1 2 3 ...的顺序不定。但是输出结果done必定是在最后的位置上的。因为dispatch_apply会等待所以的处理任务执行结束。
//假如对一个NSArray类对象的所有元素执行处理时,不必一个个编写for循环
NSArray *array = [[NSArray alloc] initWithObjects:@"string1",@"string2",@"string3", nil];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply([array count], queue, ^(size_t index){
NSLog(@"%zu : %@",index,[array objectAtIndex:index]);
});
由于dispatch_apply方法也与dispatch_sync方法相同,会等待处理执行结束,因此推荐在dispatch_async函数中非同步的执行dispatch_apply方法。
NSArray *array = [[NSArray alloc] initWithObjects:@"string1",@"string2",@"string3", nil];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//在Glocbal Dispatch Queue中非同步执行
dispatch_async(queue, ^{
//等待dispatch_apply方法中的全部处理执行结束
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply([array count], queue, ^(size_t index){
NSLog(@"%zu : %@",index,[array objectAtIndex:index]);
});
//dispatch_apply方法中的全部处理任务执行结束
dispatch_async(dispatch_get_main_queue(), ^{
//在主线程中执行处理
NSLog(@"done");
});
});
9、dispatch_suspend 和 dispatch_resume
//挂起指定的dispatch queue
dispatch_suspend(<#dispatch_object_t object#>)
//恢复指定的dispatch queue
dispatch_resume(<#dispatch_object_t object#>)
//这些方法对已经执行的处理没有影响,挂起后,追加到dispatch queue中但尚未处理的在此之后停止执行,而恢复后则使得这些处理能够继续执行。
10、dispatch_oncedispatch_once方法保证在应用程序执行中只执行一次指定处理的API。
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//code to be executed once
});