1.串行队列
(1)GCD下的dispatch_queue队列都是FIFO队列,都会按照提交到队列的顺序执行. 只是根据队列的性质,分为
<1>串行队列:用户队列、主线程队列
<2>并行队列.
(2)同步(dispatch_sync)、异步方式(dispatch_async). 配合串行队列和并行队列使用.
同步队列直接提交两个任务就可以. // 串形队列 dispatch_queue_t serilQueue = dispatch_queue_create("com.quains.myQueue", 0);
//开始时间
NSDate *startTime = [NSDate date];
__block UIImage *image = nil;
//1.先去网上下载图片
dispatch_async(serilQueue, ^{
//下载图片
});
//2.在主线程展示到界面里
dispatch_async(serilQueue, ^{
NSLog(@"%@",[NSThread currentThread]);
// 在主线程展示
dispatch_async(dispatch_get_main_queue(), ^{
//显示图片
});
//3.清理
dispatch_release(serilQueue);
[image release];
注意:
(1) __block变量分配在栈,retain下,防止被回收.
(2)dispatch要手动create和release.
(3)提交到主线程队列的时候,慎用同步dispatch_sync方法,有可能造成死锁. 因为主线程队列是串行队列,要等队列里的任务一个一个执行.所以提交一个任务到队列,如果用同步方法就会阻塞住主线程,而主线程又要等主线程队列里的任务都执行完才能执行那个刚提交的,所以主线程队列里还有其他的任务的话,但他已经被阻塞住了,没法先完成队列里的其他任务,即,最后一个任务也没机会执行到,于是造成死锁.
(4)提交到串行队列可以用同步方式,也可以用异步方式.
2.并行队列
采用并行队列的时候,可以采用同步的方式把任务提交到队列里去,即可以实现同步的方式
//新建一个队列 dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//记时
NSDate *startTime = [NSDate date];
//加入队列
dispatch_async(concurrentQueue, ^{
__block UIImage *image = nil;
//1.先去网上下载图片
dispatch_sync(concurrentQueue, ^{
//下载图片
});
//2.在主线程展示到界面里
dispatch_sync(dispatch_get_main_queue(), ^{
//显示图片
});
});
两个同步的任务用一个异步的包起来,提交到并行队列里去,即可实现同步的方式.
3.使用分组方式
group本身是将几个有关联的任务组合起来,然后提供给开发者一个知道这个group结束的点. 虽然这个只有一个任务,但是可以利用group的结束点,去阻塞线程,从而来实现同步方式.
例如让后台2个线程并行执行,然后等2个线程都结束后,再汇总执行结果。这个可以用dispatch_group, dispatch_group_async 和 dispatch_group_notify来实现,示例如下:
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
// 并行执行的线程一
});
dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
// 并行执行的线程二
});
dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{
// 汇总结果
});
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, ^{
//1.先去网上下载图片
});
// 2.等下载好了再在刷新主线程
dispatch_group_notify(group, queue, ^{
//在主线程展示到界面里
dispatch_async(dispatch_get_main_queue(), ^{
//显示图片
});
});
// 释放掉
dispatch_release(group);
dispatch_group 也要手动创建和释放. dispatch_notify()提供了一个知道group什么时候结束的点. 当然也可以使用dispatch_wait()去阻塞
4.信号量
信号量 和 琐 的作用差不多,可以用来实现同步的方式. 但是信号量通常用在 允许几个线程同时访问一个资源,通过信号量来控制访问的线程个数.
// 信号量初始化为1 dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
NSDate *startTime = [NSDate date];
__block UIImage *image = nil;
//1.先去网上下载图片
dispatch_async(queue, ^{
// wait操作-1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// 开始下载
// signal操作+1
dispatch_semaphore_signal(semaphore);
});
// 2.等下载好了再在刷新主线程
dispatch_async(dispatch_get_main_queue(), ^{
// wait操作-1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
//显示图片
// signal操作+1
dispatch_semaphore_signal(semaphore);
});
dispatch_wait会阻塞线程并且检测信号量的值,直到信号量值大于0才会开始往下执行,同时对信号量执行-1操作.
dispatch_signal则是+1操作.