串行
串行队列包括用户队列、主线程队列
-串行同步
//串行同步
dispatch_queue_t queue = dispatch_queue_create("serial_sync", nil);
dispatch_sync(queue, ^{
sleep(1);
NSLog(@"sync serial name '%@' in a process",queue);
});
NSLog(@"sync serial sync process end");
- 串行异步
//串行异步
dispatch_queue_t asynQueue = dispatch_queue_create("serial_async", nil);
dispatch_async(asynQueue, ^{
sleep(1);
NSLog(@"async serial name '%s' in a process",dispatch_queue_get_label(asynQueue));
});
NSLog(@"async serial sync process end");
并行
//并发队列 :Concurrent Queues
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t aHQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_queue_t aLQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
Demo-并行队列
- (void)testConcurrentQueue{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//记时开始
NSDate *startTime = [NSDate date];
//两个同步的任务用一个异步的包起来,提交到并行队列里去,即可实现同步的方式.
//加入队列
dispatch_async(concurrentQueue, ^{
NSLog(@"并行同步 start at %@",startTime);
__block UIImage *image = nil;
//1.先去下载图片
dispatch_sync(concurrentQueue, ^{
NSString *urlAsString = @"https://www.baidu.com/img/bdlogo.png";
NSURL *url = [NSURL URLWithString:urlAsString];
NSError *downloadError = nil;
NSData *imageData = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url] returningResponse:nil error:&downloadError];
if (downloadError == nil && imageData != nil) {
image = [UIImage imageWithData:imageData];
}
else if(downloadError != nil){
NSLog(@"error happened = %@", downloadError);
}
else{
NSLog(@"No data download");
}
});
//2.在主线程展示到界面里
__block typeof (self)weakSelf = self;
dispatch_sync(dispatch_get_main_queue(), ^{
if (image != nil) {
[weakSelf.imageView setImage:image];
NSDate *endTime = [NSDate date];
NSLog(@"并行同步 completed in %f time", [endTime timeIntervalSinceDate:startTime]);
}
else{
NSLog(@"image isn't downloaded, nothing to display");
}
});
});
}
主队列
//主队列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
分组
对分组的理解
将几个有关联的任务组合起来,然后提供一个知道这个group结束的点,接着再执行其他任务。
dispatch_notify()提供了一个知道group什么时候结束的点. 也可以使用dispatch_wait()去阻塞.见demo
Demo-简单分组
//获取并发队列:加上sleep可以更好的理解
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//创建2个queue group: a 负责任务123,b负责456
dispatch_group_t aGroup = dispatch_group_create();
dispatch_group_t bGroup = dispatch_group_create();
dispatch_group_async(aGroup, aQueue, ^{
NSLog(@"task 1 start");
sleep(3);
NSLog(@"task 1 : queue name is %s ,group name is %s",dispatch_queue_get_label(aQueue),dispatch_queue_get_label(aQueue));
});
dispatch_group_async(aGroup, aQueue, ^{
NSLog(@"task 2 start");
sleep(2);
NSLog(@"task 2 : queue name is %s ,group name is %s",dispatch_queue_get_label(aQueue),dispatch_queue_get_label(aQueue));
});
dispatch_group_async(aGroup, aQueue, ^{
NSLog(@"task 3 start");
sleep(10);
NSLog(@"task 3 : queue name is %s ,group name is %s",dispatch_queue_get_label(aQueue),dispatch_queue_get_label(aQueue));
});
NSLog(@"wait task 1,2,3.");
//等待组内任务全部完成
dispatch_group_wait(aGroup, DISPATCH_TIME_FOREVER);
NSLog(@"task 1,2,3 finished.");
//任务4
dispatch_group_async(bGroup, aQueue, ^{
NSLog(@"task 4.");
});
//任务5
dispatch_group_async(bGroup, aQueue, ^{
NSLog(@"task 5.");
});
//任务6
dispatch_group_async(bGroup, aQueue, ^{
NSLog(@"task 6.");
});
NSLog(@"wait task 4,5,6.");
//等待组内任务全部完成
dispatch_group_wait(bGroup, DISPATCH_TIME_FOREVER);
NSLog(@"task 4,5,6 finished.");
分组的例子:下载图片并展示
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
NSDate *startTime = [NSDate date];
__block UIImage *image = nil;
dispatch_group_async(group, queue, ^{
NSLog(@"分组同步 start in %@",startTime);
//1.先去网上下载图片
NSString *urlAsString = @"http://s0.hao123img.com/res/img/logo/logonew1.png";
NSURL *url = [NSURL URLWithString:urlAsString];
NSError *downloadError = nil;
NSData *imageData = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url] returningResponse:nil error:&downloadError];
if (downloadError == nil && imageData != nil) {
image = [UIImage imageWithData:imageData];
}
else if(downloadError != nil){
NSLog(@"error happened = %@", downloadError);
}
else{
NSLog(@"No data download");
}
});
__block typeof (self)weakSelf = self;
// 2.等下载好了再在刷新主线程
dispatch_group_notify(group, queue, ^{
//在主线程展示到界面里
dispatch_async(dispatch_get_main_queue(), ^{
if (image != nil) {
[weakSelf.imageView setImage:image];
NSDate *endTime = [NSDate date];
NSLog(@"分组同步 end at %@,completed in %f time",endTime, [endTime timeIntervalSinceDate:startTime]);
}
else{
NSLog(@"image isn't downloaded, nothing to display");
}
});
});
注
- concurrent queues和main queue都是由系统生成而且 dispatch_suspend, dispatch_resume, dispatch_set_context这些函数对他们无效。
- GCD下的dispatch_queue队列不管是并发队列都是FIFO队列,,都会按照提交到队列的顺序执行.
- 提交到主线程队列的时候,要慎用dispatch_sync方法,有可能造成死锁. 因为主线程队列是串行队列,要等队列里的任务一个一个执行.所以提交一个任务到队列,如果用同步方法就会阻塞住主线程,而主线程又要等主线程队列里的任务都执行完才能执行刚提交的,所以主线程队列里还有其他的任务的话,但他已经被阻塞住了,没法先完成队列里的其他任务,即,最后一个任务也没机会执行到,于是造成死锁.
- 提交到串行队列可以用同步方式,也可以用异步方式.
- 采用并行队列的时候,可以采用同步的方式把任务提交到队列里去,即可以实现同步的方式(两个同步的任务用一个异步的包起来,提交到并行队列里去,即可实现同步的方式.)
如有不对,请指正。谢谢