一.队列
- 全局队列:dispatch_get_global_queue(),全局队列是并发队列,添加进这个队列的任务会并发执行,开启多条线程。
- 主队列:dispatch_get_main_queue(),主队列是串行队列,在主线程执行添加进队列的任务,任务是一个一个执行的,先进来的先执行。
- 自定义队列:dispatch_queue_t,自定义队列可以是串行,也可以是并发。
二.异步同步
- 异步:异步执行,会新开一条线程来执行任务,主队列除外,主队列异步,会将任务添加到队列上,主线程执行完当前任务就去执行添加进来的任务,dispatch_async(queue,^{ 任务 })。
- 同步:同步执行是在当前线程上执行任务,不会新开线程,dispatch_sync(queue,^{ 任务 })。
三.常用方法
- dispatch_after... : 延迟多少秒执行
//DISPATCH_TIME_NOW:从现在开始执行
//延迟多少秒
//执行的代码块
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"block");
});
- dispatch_one ... : 只执行一次的操作,可以用来创建单例类,只初始化一次内存
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"1");
});
- dispatch_barrier_async() : 控制任务的执行顺序,在它前面的先执行,前面的执行完才执行后面的
//并发执行,先执行12,然后3,然后45
dispatch_queue_t queue1 = dispatch_queue_create("com.example.myqueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue1, ^{
NSLog(@"1");
});
dispatch_async(queue1, ^{
NSLog(@"2");
});
dispatch_barrier_async(queue1, ^{
NSLog(@"3");
});
dispatch_async(queue1, ^{
NSLog(@"4");
});
dispatch_async(queue1, ^{
NSLog(@"5");
});
- dispatch_group_t,dispatch_group_async,dispatch_group_notify : 队列组,先执行async的任务,再做notify的任务,一般用于并发队列,需要什么先做好,才能配置下一步,比如下载图片,更新UI。
//打印结果为123随意顺序,后面d再打印done
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"1");
});
dispatch_group_async(group, queue, ^{
NSLog(@"2");
});
dispatch_group_async(group, queue, ^{
NSLog(@"3");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"done");
});
四.死锁
就是线程柱塞,可能造成的原因:
一个串行队列,加了一个异步的任务,异步任务里面加了个同步操作在串行队列上,异步任务会新开一条线程去执行任务,执行到里面的同步任务,串行队列会执行这个同步任务,但是这时候异步操作还没结束,串行队列不能去执行同步任务,相互等待,就造成了死锁。
//死锁,要主线程同步执行1
dispatch_queue_t queue2 = dispatch_get_main_queue();
dispatch_async(queue2, ^{
dispatch_sync(queue2, ^{
NSLog(@"1");
});
});
解决方法:
将同步任务改为异步,就会将任务添加到串行队列上,而且排在异步任务后面
五.信号量
dispatch_semapore提供了三个函数
- dispatch_semaphore_create : 创建一个Semaphore并初始化信号的总量
- dispatch_semaphore_signal : 发送一个信号,让信号总量加一
- dispatch_semaphore_wait : 可以使信号量总量减一,信号总量为0,就是一直等待,不为0就可以正常执行
//保证串行队列多个线程,每次只有一个线程对数组添加数据
dispatch_queue_t queue3 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//创建一个信号为1的信号量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
NSMutableArray *array = [[NSMutableArray alloc]init];
for (int i = 0; i < 1000; ++i) {
dispatch_async(queue3, ^{
//信号大于等于1的时候dispatch_semaphore_wait会将信号减一,然后返回,信号小于1的时候就等待
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[array addObject:[NSString stringWithFormat:@"%d",i]];
//将信号加1
dispatch_semaphore_signal(semaphore);
});
}
可以实现同步并行队列
应用:YYCache框架里面就用了信号量来保证大容量缓存的线程安全
网友评论