如何用?
1.串行队列同步执行
dispatch_queue_t queue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
for (int i = 0; i < 10; i ++) {
NSLog(@"%d,同步执行当前线程%@",i,[NSThread currentThread]);
};
});
dispatch_sync(queue, ^{
for (int i = 0; i < 10; i ++) {
NSLog(@"%d,====同步执行当前线程%@",i,[NSThread currentThread]);
};
});
2.串行队列异步执行
dispatch_queue_t queue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
for (int i = 0; i < 10; i ++) {
NSLog(@"%d,异步执行当前线程%@",i,[NSThread currentThread]);
};
});
dispatch_async(queue, ^{
for (int i = 0; i < 10; i ++) {
NSLog(@"%d,====异步执行当前线程%@",i,[NSThread currentThread]);
};
});
3.并发队列同步执行
dispatch_queue_t queue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
for (int i = 0; i < 10; i ++) {
NSLog(@"%d,同步执行当前线程%@",i,[NSThread currentThread]);
};
});
dispatch_sync(queue, ^{
for (int i = 0; i < 10; i ++) {
NSLog(@"%d,-------同步执行当前线程%@",i,[NSThread currentThread]);
};
});
4.并发队列异步执行
dispatch_queue_t queue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
for (int i = 0; i < 10; i ++) {
NSLog(@"%d,异步执行当前线程%@",i,[NSThread currentThread]);
};
});
dispatch_async(queue, ^{
for (int i = 0; i < 10; i ++) {
NSLog(@"%d,-------异步执行当前线程%@",i,[NSThread currentThread]);
};
});
dispatch_queue_t queue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
for (int i = 0; i < 10; i ++) {
NSLog(@"%d,异步执行当前线程%@",i,[NSThread currentThread]);
};
});
dispatch_barrier_async(queue, ^{
for (int i = 0; i < 10; i ++) {
NSLog(@"%d,-------异步执行当前线程%@",i,[NSThread currentThread]);
};
});
dispatch_async(queue, ^{
for (int i = 0; i < 10; i ++) {
NSLog(@"%d,========异步执行当前线程%@",i,[NSThread currentThread]);
};
});
dispatch_barrier_async(),一般用在并发队列中,他会先看队列中有没有其他的任务要执行,如果有的话,则等其他任务执行完,再执行,同时在此方法后添加的任务必须等待此方法中任务执行后才能执行。可以用来控制执行顺序。比如加载十张图片,你希望某张图片最先加载。将该图片的加载任务加入barrier_async中,其他图片加载任务放在async中。即可控制。
dispatch_group_t groupQueue = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);//全局并发队列
dispatch_group_async(groupQueue, queue, ^{
for (int i = 0; i < 10; i ++) {
NSLog(@"%d,异步执行当前线程%@",i,[NSThread currentThread]);
};
});
dispatch_group_async(groupQueue, queue, ^{
for (int i = 0; i < 1000; i ++) {
NSLog(@"%d,----------异步执行当前线程%@",i,[NSThread currentThread]);
};
});
dispatch_group_notify(groupQueue, queue, ^{
NSLog(@"队列组中的任务全都执行完毕啦!");
});
队列组:顾名思义,就是将所有队列加入一个组中,方便控制队列的启动和结束。比如,你需要下载n张图片,当n张图片都下载完成后,你需要把这n张图拼接成一张图片(或者弹个提示框,图片全部下载完毕)之类的。反正就是需要知道所有的任务都执行完毕。怎么做?1.bool值标记所有队列任务。2.用队列组。将队列加入group中,当所有任务执行完毕,group_notify回调通知。在这个block里面处理之后的任务。
7.dispatch_once()
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
/..../
});
单次执行一个任务,此方法中的任务只会执行一次,重复调用也没办法重复执行(单例模式中常用此方法)。
8.定时器
static dispatch_source_t _timer;
NSTimeInterval period = 3.0; //设置时间间隔
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), period * NSEC_PER_SEC, 0); //period秒执行
// 事件回调
dispatch_source_set_event_handler(_timer, ^{
dispatch_async(dispatch_get_main_queue(), ^{
/任务,看你自己的需求.../
});
});
// 开启定时器
dispatch_resume(_timer);
// 关闭定时器
// dispatch_source_cancel(_timer);
线程锁,资源抢占问题
假如,我们有一个数据库,存储了十条数据,现在有十五条线程,去访问这十条数据(数据量很大)。这就出现了资源竞争的情况,如何保证这十条数据都能确切的被访问到?
为了直观的描述这个问题,上代码
//初始化锁对象
//_lock=[[NSLock alloc]init];
_dataArray = [NSMutableArray arrayWithCapacity:10];
for (int i = 0; i < 10; i ++) {
[_dataArray addObject:@(2)];
}
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
for (int i = 0; i < 15; i ++) {
dispatch_async(queue, ^{
// NSLog(@"我是第%d条线程",i+1);
[self handleData:i];
});
}
- (void)handleData:(int)cout {
//先判断_dataArray是否有数据,如果有,则进行读取
//[_lock lock];
if (_dataArray.count > 0) {
NSLog(@"第%d条线程访问了这个数据,_dataArray有%lu个数据",cout+1,(unsigned long)_dataArray.count);
[NSThread sleepForTimeInterval:[[_dataArray lastObject] intValue]];//模拟读文件,因为不好找这么大的文件,用这个代替,相当于读取_dataArray的lastObj,耗费了几秒钟。
[_dataArray removeLastObject];
}
//[_lock unlock];
}
不加锁的打印情况:
1.sleep2秒
因为_dataArray数据抢占问题,最后一个元素被多条线程持有,remove崩溃。
2.sleep0秒
可以很直观的看到,多条线程访问了同一个数据!如果这个数据比较重要,比如火车票,那多个人都定了这张票,给谁好??
所以。对于这种资源抢占的情况,我们必须要对这段代码加锁。保证这段代码在某个线程中执行完之后,才能被另外一个线程访问。
打开[_lock lock unlock]注释即可。
或者采用@synchronized的方式加同步锁
@synchronized(self) {
if (_dataArray.count > 0) {
NSLog(@"第%d条线程访问了这个数据,_dataArray有%lu个数据",cout+1,(unsigned long)_dataArray.count);
// [NSThread sleepForTimeInterval:[[_dataArray lastObject] intValue]];//模拟读文件,因为不好找这么大的文件,用这个代替,相当于读取_dataArray的lastObj,耗费了几秒钟。
[_dataArray removeLastObject];
}
}