为何dispatch_get_main_queue异步块执行顺序与预期不符?
为什么主队列异步任务的输出顺序是1、2、3而不是1、3、2?
先看你的代码:
- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"1"); dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"3"); }); NSLog(@"2"); }
哈哈这个问题我刚接触GCD的时候也困惑过!核心原因得从主队列的本质和dispatch_async的工作机制说起:
- 首先,主队列是一个串行队列,而且它的所有任务都只会在主线程上执行。串行队列的特点是:必须等当前正在执行的任务完全结束,才会取下一个任务执行。
- 其次,
dispatch_async的作用是把任务异步提交到指定队列的末尾,它不会阻塞当前的执行流程——也就是说,提交完任务后,当前代码会继续往下走,不会等着这个新任务执行。
现在我们一步步拆解你的代码执行流程:
- 进入
viewDidLoad,先调用[super viewDidLoad];,然后执行NSLog(@"1");,控制台输出1。 - 调用
dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"3"); });:这时候你是把打印3的block提交到主队列的任务末尾。但注意,当前主队列正在执行的任务就是viewDidLoad这个方法本身,所以这个新的打印任务必须等viewDidLoad里的所有同步代码都执行完,才会被轮到执行。 - 继续执行
NSLog(@"2");,控制台输出2。 - 等
viewDidLoad整个方法执行完毕,主队列的当前任务结束了,这时候才会从队列里取出刚才提交的block,执行NSLog(@"3");,输出3。
如果换成dispatch_sync(同步提交)到主队列,那结果就会是1、3、2了——因为同步提交会阻塞当前任务,必须等提交的任务执行完,当前代码才会继续往下走。但异步提交不会,它只是“排队”,等当前任务干完再轮到它。
内容的提问来源于stack exchange,提问作者yong ho
相关产品推荐
相关产品推荐

