要求
先完成TaskA和TaskB【TaskA、TaskB无先后顺序要求】之后再执行TaskC?
知识拓展
2种队列
- 并发队列
队列中的任务同时执行
- 串形队列
队列中的任务顺序执行
- 主队列
具有特定作用的串形队列,比如更新UI
2种函数
- dispatch_sync同步函数
不具备开启新线程的能力,只能在当前线程中执行
会阻塞当前线程,并立即执行当前的同步函数,直到同步函数执行完毕,之后才继续运行
dispatch_sync会阻塞当前正在运行的外围queue,要求在queue中加入新的block任务并请求立即在该queue中执行该block任务
- dispatch_async异步函数
具备开启新线程的能力,但不一定开启新线程
不会阻塞当前线程
dispatch_async(queue, ^{//dispatch_async不会阻塞当前正在运行的外围queue,仅仅是要求在queue中加入新的block任务,等待时机成熟时再请求在该queue中执行该block任务
解法一:
- (void)groupSimpleAsync {
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create("customequeue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group, queue, ^{
/*TASK A 为异步任务*/
dispatch_async(queue, ^{
for (int i = 0; i < 5; i++) {
sleep(5);
NSLog(@"current %@, index => %d", @"async task---A", i);
}
});
});
dispatch_group_async(group, queue, ^{
/*TASK B 为异步任务*/
dispatch_async(queue, ^{
for (int i = 0; i < 5; i++) {
sleep(3);
NSLog(@"current %@, index => %d", @"async task===B", i);
}
});
});
dispatch_group_notify(group, queue, ^{
NSLog(@"all over now=》Task C");
});
}
点评
不能达到期望效果
解法二
- (void)groupSimpleSync {
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create("customequeue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group, queue, ^{
/*TASK A 为同步任务*/
dispatch_sync(queue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"current %@, index => %d", @"async---1", i);
sleep(5);
}
});
});
dispatch_group_async(group, queue, ^{
/*TASK B 为同步任务*/
dispatch_sync(queue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"current %@, index => %d", @"async===2", i);
sleep(3);
}
});
});
dispatch_group_notify(group, queue, ^{
NSLog(@"all over now");
});
}
点评
达到期望效果
解法三
- (void)groupEnterAndLeave {
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create("customequeue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_enter(group);
/*TASK A 为异步任务*/
dispatch_async(queue, ^{
for (int i = 0; i < 5; i++) {
sleep(5);
NSLog(@"current %@, index => %d", @"async task---A", i);
}
dispatch_group_leave(group);
});
dispatch_group_enter(group);
/*TASK B 为异步任务*/
dispatch_async(queue, ^{
for (int i = 0; i < 5; i++) {
sleep(3);
NSLog(@"current %@, index => %d", @"async task===B", i);
}
dispatch_group_leave(group);
});
dispatch_group_notify(group, queue, ^{
NSLog(@"all over now=》Task C");
});
}
点评
可以达到期望效果
部分说明
- 如果子任务是同步任务,可以直接
dispatch_group_async + dispatch_group_notify
达到期望效果 - 如果子任务是异步任务,可以使用
dispatch_group_enter+dispatch_async+dispatch_group_leave+dispatch_group_notify
达到期望效果
更多细节体会
- (void)serialQueueAndSync {
//此时的操作:
//外围queue:在主线程main queue中运行
//新开serial queue
dispatch_queue_t queue = dispatch_queue_create("DISPATCH_QUEUE_SERIAL", DISPATCH_QUEUE_SERIAL);
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"Start", [NSThread currentThread]);
dispatch_sync(queue, ^{//dispatch_sync会阻塞当前正在运行的外围queue,要求在queue中加入新的block任务并请求立即在该queue中执行该block任务
// 此时的操作:
// 阻塞外围queue:main queue,立即切换到serial queue中,serial queue是一个串形队列
// 并把当前block任务加入到serial queue中,
// 加入完成之后会立即在serial queue中执行该block任务
// 执行完成之后回到main queue,
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"Task 1", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"Task 2", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"Task 3", [NSThread currentThread]);
});
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"End", [NSThread currentThread]);
}
- (void)mainQueueAndSync {
//此时的操作:
//外围queue:在主线程main queue中运行
//得到main queue
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"Start", [NSThread currentThread]);
dispatch_sync(queue, ^{//dispatch_sync会阻塞当前正在运行的外围queue,要求在queue中加入新的block任务并请求立即在该queue中执行该block任务
// 此时的操作:
// 阻塞外围queue:main queue,main queue默认是一个串形队列
// 并把当前block任务加入到queue中
// 加入完成之后会请求立即在queue中执行该block任务
// 然而,此时的queue恰恰是main queue
// 由于main queuey在之前已经被阻塞了,此处已经无法等待到main queue,
// 从而导致死锁的发生
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"Task 1", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"Task 2", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"Task 3", [NSThread currentThread]);
});
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"End", [NSThread currentThread]);
}
- (void)mainQueueAndAsync {
//此时的操作:
//外围queue:在主线程main queue中运行
//得到main queue
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"Start", [NSThread currentThread]);
dispatch_async(queue, ^{//dispatch_async不会阻塞当前正在运行的外围queue,仅仅是要求在queue中加入新的block任务,等待时机成熟时再请求在该queue中执行该block任务
// 此时的操作:
// 不阻塞main queue,main queue默认是一个串形队列
// 仅仅是把当前block任务加入到main queue中,不要求立即执行block任务
// 等待时机成熟时再请求在main queue中执行该block任务
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"Task 1", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"Task 2", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"Task 3", [NSThread currentThread]);
});
NSLog(@"%s: ======= %@ -- %@ =====", __func__, @"End", [NSThread currentThread]);
}
其他
其他的实现方法还有哪些?