GCD队列与任务
GCD的基本思想:
GCD的基本思想就是将操作a放在队列a中去执行:
(1)操作使用blocks定义
(2)队列负责调度任务执行所在的线程以及具体的执行时间
(3)队列的特点是先进先出(FIFO)的,新添加至队列的操作都会排在队尾
提示:
GCD的函数都是以dispatch(分派、调度)开头的
列队:
dispatch_queue_t:
(1)串行队列,队列中的任务只会顺序执行
(2)并行队列,队列中的任务通常会并发执行
操作:
(1)dispatch_async 异步操作,会并发执行,无法确定任务的执行顺序
(2)dispatch_sync 同步操作,会依次执行顺序执行,能够决定任务的执行操作
OK!以上说了点基础知识;现在直接上代码来讲解:
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self gcdDemo1];
// [self gcdDemo2];
}
#pragma mark - GCD方法
#pragma mark - 串行队列
- (void)gcdDemo1
{
//将操作放在队列中
//在C语言函数中,定义类型,绝大多数的结尾是_t或ref
//串行队列的异步操作非常有用;
//应用案例:
//1>从网络上下载图片
//2>滤镜 (高光,红眼...)
// 先执行第一个在执行第二个,就可以使用这个 串行队列的异步操作
dispatch_queue_t q = dispatch_queue_create("www.hupeng.com", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i < 10; ++i) {
dispatch_async(q, ^{
NSLog(@"%@",[NSThread currentThread]);
});
}
}
#pragma mark - 并行队列
- (void)gcdDemo2
{
dispatch_queue_t q = dispatch_queue_create("www.hupeng.com", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 10; ++i) {
dispatch_async(q, ^{
NSLog(@"%@",[NSThread currentThread]);
});
}
}
@end
上面有串行队列和并行队列的异步操作;
串行队列异步操作结果如下:
并行队列异步操作结果如下:
现在在串行队列中执行同步操作:
- (void)gcdDemo1
{
dispatch_queue_t q = dispatch_queue_create("www.hupeng.com", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i < 10; ++i) {
dispatch_sync(q, ^{
NSLog(@"%@",[NSThread currentThread]);
});
}
} 执行结果为:
串行队列中同步异步一起执行:
- (void)gcdDemo1
{
dispatch_queue_t q = dispatch_queue_create("www.hupeng.com", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i < 10; ++i) {
dispatch_sync(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}
for (int i = 0; i < 10; ++i) {
dispatch_async(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}
} 执行结果如下:
并行队列中同步操作:
- (void)gcdDemo2
{
dispatch_queue_t q = dispatch_queue_create("www.hupeng.com", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 10; ++i) {
dispatch_sync(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}
} 执行结果如下:
并行队列中先同步后异步操作:
- (void)gcdDemo2
{
dispatch_queue_t q = dispatch_queue_create("www.hupeng.com", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 10; ++i) {
dispatch_sync(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}
for (int i = 0; i < 10; ++i) {
dispatch_async(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}
} 执行结果如下:
并行队列中先异步后同步操作:
- (void)gcdDemo2
{
dispatch_queue_t q = dispatch_queue_create("www.hupeng.com", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 10; ++i) {
dispatch_async(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}
for (int i = 0; i < 10; ++i) {
dispatch_sync(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}
} 执行结果如下:
从以上看来,
1,串行队列比并发队列好用,特别是串行队列异步操作
2,并行队列容易出错,并行队列不能控制新建线程数量
3,在非ARC开发,别忘记release // dispatch_release(q);
补充:
全局队列(苹果为了方便多线程的设计,提供一个全局队列,供所有的APP共同使用)
代码如下:
- (void)gcdDemo3
{
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 10; ++i) {
dispatch_sync(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}
for (int i = 0; i < 10; ++i) {
dispatch_async(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}
} 执行结果如下:
结果和并行队列的结果一样,但是它们有区别
1,全局队列不需要创建,直接GET就能用
2,两个队列的执行效果一样
3,全局队列没有名称,调试时,无法确定准确队列
还有一个 主线程队列:
每一个应用程序都只有一个主线程,为什么需要在主线程上工作呢?在IOS开发中,多有UI的更新工作,都必须在主线程中完成。
- (void)gcdMain
{
dispatch_queue_t q = dispatch_get_main_queue();
//异步操作
for (int i = 0; i < 10; ++i) {
dispatch_async(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
}
} 执行结果如下:
那别人会问还有主线程队列的同步操作呢?其实主线程队列中不能执行同步操作,只能执行异步操作;这是为什么呢?
因为在主线程队列中,先把主线程取出来,必须等主线程用完,结束了,才会把同步操作从主线程队列中取出来执行;但是主线程是一直工作的,除非将程序杀掉、结束,否则主线程永远不会结束,同步操作永远都不会取出来。
你可以自己试试,看看会不会执行;