NSOperationQueue调用waitUntilAllOperationsAreFinished导致实例晚释放问题
根因分析
使用waitUntilAllOperationsAreFinished时出现内存释放延迟的核心原因有两个:
- 该方法会阻塞当前调用线程,线程关联的自动释放池需要等到线程从阻塞状态恢复、完成当前所有任务后才会执行内存回收,已经执行完成的Operation实例会被临时暂存在释放池中,无法即时释放。
- 你当前
CustomOperation的main方法中,asyncAfter闭包强持有了Operation实例本身,也会拉长实例的持有周期。
解决方案
方案1:替换阻塞等待逻辑(推荐,无性能损耗)
完全不需要使用waitUntilAllOperationsAreFinished阻塞线程,通过添加依赖收尾操作的方式实现"所有任务完成后执行指定逻辑"的需求,同时保证每个Operation执行完毕就立即释放:
DispatchQueue.global().async { // 定义收尾操作,所有业务操作完成后才会执行 let finishOperation = BlockOperation { print("All Tasks Done") } (0...5).forEach { let customOp = CustomOperation(value: $0) // 给收尾操作添加依赖,确保所有业务操作跑完才执行收尾逻辑 finishOperation.addDependency(customOp) self.queue.addOperation(customOp) } self.queue.addOperation(finishOperation) }
该方案既满足你的业务需求,还不会浪费线程资源做无意义的阻塞,是Operation队列的标准最佳实践。
方案2:保留wait逻辑的优化方式
如果必须使用waitUntilAllOperationsAreFinished,可以通过两个修改实现即时释放:
- 修复
CustomOperation中的循环引用,将asyncAfter闭包对self的强引用改为弱引用 - 在添加Operation的逻辑外层包裹局部自动释放池
修改后的CustomOperation相关代码:
override func main() { print("Begin Task \(value)") DispatchQueue.global().asyncAfter(deadline: .now()+DispatchTimeInterval.seconds(value)) { [weak self] in guard let self = self else { return } print("Finish Task \(self.value)") self.finish() } }
修改后的调用逻辑:
DispatchQueue.global().async { (0...5).forEach { value in autoreleasepool { self.queue.addOperation(CustomOperation(value: value)) } } self.queue.waitUntilAllOperationsAreFinished() print("All Tasks Done") }
以上两个方案都可以实现Operation执行完毕后立即触发deinit,不会等到所有任务全部完成再释放。
内容的提问来源于stack exchange,提问作者anb
相关产品推荐
相关产品推荐

