GCD使用介绍:2-队列与任务的组合
在GCD中存在队列和任务两个核心概念,同时队列又分为并行队列、串行队列和主队列,任务包括异步任务和同步任务。GCD的使用方法就是把任务放到队列中执行,因而根据不同的任务类型和队列类型,就会存在6种组合。
1、异步任务+并行队列
把异步任务放到并行队列进行执行,异步任务会在不同的线程中执行,这是最常使用的一种组合。
//获取并行队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//创建异步任务,并放到并行队列中执行
dispatch_async(queue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task1:%d",i);
}
NSLog(@"task1----%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task2:%d",i);
}
NSLog(@"task2----%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task3:%d",i);
}
NSLog(@"task3----%@",[NSThread currentThread]);
});
运行结果如下。异步任务+并行队列组合情况下,每个任务会在不同的线程中同时执行。
2、异步任务+串行队列
对于异步任务放在串行队列中执行时,任务只会在一个新开的线程中,按照顺序进行执行。
//创建串行队列
dispatch_queue_t queue = dispatch_queue_create("com.99ios", NULL);
//创建异步任务
dispatch_async(queue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task1:%d",i);
}
NSLog(@"task1----%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task2:%d",i);
}
NSLog(@"task2----%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task3:%d",i);
}
NSLog(@"task3----%@",[NSThread currentThread]);
});
运行结果如下。可以看到,所有任务都在一个线程中执行,并且完成一个后,再执行下一个。
3、异步任务+主队列
把异步任务放在主队列中执行,由于主队列是一个特殊的串行队列,因此任务是串行执行的,但由于主队列对应序号为1的线程,因此,即便是异步任务,也不会再创建新的线程。
//获取主队列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
//创建异步任务
dispatch_async(mainQueue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task1:%d",i);
}
NSLog(@"task1----%@",[NSThread currentThread]);
});
dispatch_async(mainQueue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task2:%d",i);
}
NSLog(@"task2----%@",[NSThread currentThread]);
});
dispatch_async(mainQueue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task3:%d",i);
}
NSLog(@"task3----%@",[NSThread currentThread]);
});
运行结果如下:
4、同步任务+并行队列
同步任务的执行是在当前线程中完成的,因此,即便是把同步任务放在并行队列中执行,由于只有1个线程,任务也是一个一个按顺序执行的(串行执行)。
- (void)viewDidLoad {
[super viewDidLoad];
//获取并行队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//同步执行
dispatch_sync(queue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task1:%d",i);
}
NSLog(@"task1----%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task2:%d",i);
}
NSLog(@"task2----%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task3:%d",i);
}
NSLog(@"task3----%@",[NSThread currentThread]);
});
}
运行结果如下,由于viewDidLoad方法是在主线程中执行的,因此,创建的同步任务也在主线程中执行。
5、同步任务+串行队列
同步任务放在串行队列中执行,任务会在当前线程依次执行。
- (void)viewDidLoad {
[super viewDidLoad];
//创建串行队列
dispatch_queue_t queue = dispatch_queue_create("com.99ios", NULL);
//同步执行
dispatch_sync(queue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task1:%d",i);
}
NSLog(@"task1----%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task2:%d",i);
}
NSLog(@"task2----%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task3:%d",i);
}
NSLog(@"task3----%@",[NSThread currentThread]);
});
}
运行结果如下,由于viewDidLoad方法是在主线程中执行的,因此,创建的同步任务也在主线程中执行。
6、同步任务+主队列
这种情况下,主线程会被阻塞,程序会挂死,不能使用!
//获取主队列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
//同步执行
//1
dispatch_sync(mainQueue, ^{ //block 1
for (int i = 0; i<2; i++) {
NSLog(@"task1:%d",i);
}
NSLog(@"task1----%@",[NSThread currentThread]);
});
//2
dispatch_sync(mainQueue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task2:%d",i);
}
NSLog(@"task2----%@",[NSThread currentThread]);
});
//3
dispatch_sync(mainQueue, ^{
for (int i = 0; i<2; i++) {
NSLog(@"task3:%d",i);
}
NSLog(@"task3----%@",[NSThread currentThread]);
});
当调用dispatch_sync
会阻塞线程,直到任务(block
)执行完成之后才能继续执行。主线程中初始时需要执行的代码如下所示。主线程需要执行1,2,3三块代码。
执行完1之后主线程需要执行的代码如下所示。将任务(block
)添加到主线程中去执行。同时阻塞主线程,直到任务(block
)执行完成。此时block 1
等待3的代码执行完成,而代码1需要等block 1
执行完成。这就造成了1
和block 1
相互等待,成了死锁。
示例代码
https://github.com/99ios/11.2.2
最后编辑时间为: September 13th , 2017 at 03:09 pm
本文由 99ios 创作,转载请注明出处