将BlockOperation加入OperationQueue后为何后续代码会继续执行?
Operation加入队列后不阻塞后续代码的原因
首先要明确两个容易混淆的核心概念,"Operation默认同步执行"的结论存在适用前提:
- Operation默认同步执行的成立场景是手动调用
start()方法启动操作:同步操作不会自行创建新线程,调用start()的当前线程会阻塞,等待操作的任务逻辑全部执行完毕后,才会继续运行start()之后的代码。 OperationQueue是独立的任务调度器,默认工作在并发模式:你调用addOperation(_:)提交任务时,方法会立刻返回,不会等待任务执行完成。队列会自行管理线程池,把提交的操作分配到非当前调用线程的其他线程上启动执行,根本不会阻塞当前代码所在的线程。
对应的测试代码如下:
let op = BlockOperation(block: { print("Done") }) let qu = OperationQueue() qu.addOperation(op) print("after!")
实际运行输出顺序为:
after!
Done
出现这个执行顺序的具体逻辑:
- 示例中创建的
BlockOperation确实是默认的同步操作,它的isAsynchronous属性默认返回false,但这个属性仅在手动启动操作时生效,用来标识操作是否会自己管理生命周期、异步执行,对加入队列的操作来说,这个标记不会影响队列的调度逻辑。 - 当代码运行在主线程时,调用
qu.addOperation(op)只是把操作提交到队列的待调度列表,队列会取出可用的后台线程,在后台线程上调用操作的start()方法执行block。这个过程完全不占用主线程的执行时间,所以主线程会立刻继续往下走,先执行print("after!")。等后台线程调度到这个操作时,才会执行block打印"Done"。
如果要验证同步操作的特性,可以把提交队列的代码换成直接手动启动操作:
let op = BlockOperation(block: { print("Done") }) op.start() // 手动在当前线程启动同步操作 print("after!")
这时输出顺序就会变成先打印"Done",再打印"after!",符合同步操作阻塞当前调用线程的特性。
内容的提问来源于stack exchange,提问作者daniel
相关产品推荐
相关产品推荐

