Operation源码分析

2,276 阅读8分钟

前言

NSOperation是Foundation中用于多线程并发任务的抽象类,它可以放到NSOperationQueue任务队列中去执行。它底层还是基于GCD来实现的,相比GCD它支持取消操作和依赖管理。

Apple用swift重写了Foundation库并且开源,可以通过阅读NSOperation的swift源代码来了解其实现原理。

github.com/apple/swift… 点击跳转

在分析源代码之前也请阅读一下苹果的《Concurrency Programming Guide》的Operation Queues一章,要了解如何使用Operation。

同步和异步

NSOperation是抽象类,使用它需要子类继承它,并覆写一些成员方法。

它有两种模式,一种是同步执行,一种是异步执行。

同步执行,需要覆写main方法即可。

@interface MyOperation : NSOperation
@end

@implementation MyOperation
- (void)main {
  // 要实现的业务逻辑写这里即可
}
@end

当main方法返回的时候,任务也就结束了。

异步执行,需要覆写start方法,同时实现asynchronous、concurrent、executing和finished属性。

@interface MyOperation : NSOperation {
  BOOL _executing;
  BOOL _finished;
}

@property (nonatomic, assign, getter = isExecuting) BOOL executing;
@property (nonatomic, assign, getter = isFinished) BOOL finished;

@end

@implementation MyOperation

@synthesize executing = _executing;
@synthesize finished = _finished;

- (void)start {
  // 要实现的业务逻辑写这里即可
}

- (BOOL)isAsynchronous {
    return YES;
}

- (BOOL)isConcurrent {
    return YES;
}

- (void)setFinished:(BOOL)finished {
    [self willChangeValueForKey:@"isFinished"];
    _finished = finished;
    [self didChangeValueForKey:@"isFinished"];
}

- (void)setExecuting:(BOOL)executing {
    [self willChangeValueForKey:@"isExecuting"];
    _executing = executing;
    [self didChangeValueForKey:@"isExecuting"];
}
@end

当start方法返回的时候,任务可以继续执行,直到任务真正执行完毕,我们执行self.finished=YES; self.executing=YES;通过KVO的方式通知NSOperation任务已经执行完毕,可以从NSOperationQueue中移除此任务了。

OperationQueue

OperationQueue是任务的执行队列

初始化

OperationQueue有两个初始化方法:

一个是public方法给大家创建任务队列使用的

open class OperationQueue : NSObject, ProgressReporting {

    // 任务队列名字
    var __name: String?

    // 对外的初始化方法
    public override init() {
        super.init()
        __name = "NSOperationQueue (Unmanaged<OperationQueue>.passUnretained(self).toOpaque())"
    }
}

另一个是internal方法,专门用来初始化mainQueue的

extension OperationQueue {
    public static let defaultMaxConcurrentOperationCount: Int = -1
}

open class OperationQueue : NSObject, ProgressReporting {

    // 是否是主线程队列
    var __mainQ: Bool = false

    // 并发数上限
    var __maxNumOps: Int = OperationQueue.defaultMaxConcurrentOperationCount

    // 实际并发数上限
    var __actualMaxNumOps: Int32 = .max

    // 任务队列名字
    var __name: String?

    // QOS,任务队列的优先级
    var __propertyQoS: QualityOfService?

    // asMainQueue是一个空元组,只是为了重载init方法,方便内部使用
    internal init(asMainQueue: ()) {
        super.init()
        __mainQ = true
        __maxNumOps = 1
        __actualMaxNumOps = 1
        __name = "NSOperationQueue Main Queue"
#if canImport(Darwin)
        __propertyQoS = QualityOfService(qos_class_main())
#else
        __propertyQoS = QualityOfService.userInteractive
#endif
    }

    // 返回主线程任务队列
    open class var main: OperationQueue {
        get {
            struct Once {
                // 使用static保证了变量只初始化一次
                static let mainQ = OperationQueue(asMainQueue: ())
            }
            return Once.mainQ
        }
    }
}

添加任务

添加一个Operation到任务队列中,对外提供了两个方法,可以添加单个任务或者批量任务。

open class OperationQueue : NSObject, ProgressReporting {
    
    // 添加单个任务
    open func addOperation(_ op: Operation) {
        _addOperations([op], barrier: false)
    }
    
    // 添加多个任务,同时支持设置是否同步等待
    open func addOperations(_ ops: [Operation], waitUntilFinished wait: Bool) {
        _addOperations(ops, barrier: false)
        if wait {
            for op in ops {
                op.waitUntilFinished()
            }
        }
    }
}

对内提供了一个下划线开头的批量添加任务方法,所有的添加任务,都最终会走到此方法中

open class OperationQueue : NSObject, ProgressReporting {

    internal func _addOperations(_ ops: [Operation], barrier: Bool = false) {
        // 判空保护
        if ops.isEmpty { return }
        
        // 失败数
        var failures = 0
        
        // 成功数
        var successes = 0

        // 第一个新任务
        var firstNewOp: Unmanaged<Operation>?

        // 上一个新任务
        var lastNewOp: Unmanaged<Operation>?

        // 循环传入的任务数组
        for op in ops {

            // 对op的状态进行CAS修改,从initialized修改成enqueuing
            if op._compareAndSwapState(.initialized, .enqueuing) {

                // 如果修改成功,成功数累加1
                successes += 1

                // 判断之前的修改是否都成功
                if 0 == failures {

                    // 走到这里,说明所有的任务的状态都正确修改成enqueuing

                    // retain一下任务对象
                    let retained = Unmanaged.passRetained(op)

                    // 如果任务的没有未完成的依赖任务,则为isReady为YES,缓存到_cachedIsReady
                    op._cachedIsReady = op.isReady

                    // GCD的工作对象
                    let schedule: DispatchWorkItem
                    
                    // 创建GCD的工作对象
                    if let qos = op.__propertyQoS?.qosClass {
                        // 任务有设置过QoS,enforceQoS表示使用传入的qos
                        schedule = DispatchWorkItem.init(qos: qos, flags: .enforceQoS, block: {
                            // 当工作对象放入DispatchQueue的时候,会开始执行此block
                            // self是OperationQueue对象,执行其_schedule方法,来调度任务
                            self._schedule(op)
                        })
                    } else {
                        // 任务没有设置过Qos,assignCurrentContext表示使用当前线程的Qos
                        schedule = DispatchWorkItem(flags: .assignCurrentContext, block: {
                            // 重复代码,同上
                            self._schedule(op)
                        })
                    }
                    
                    // 调用Operation的_adopt方法,设置__queue和__schedule成员变量
                    op._adopt(queue: self, schedule: schedule)

                    // 任务队列实际上是双向链表存储,设置任务的前后链表节点
                    op.__previousOperation = lastNewOp
                    op.__nextOperation = nil
                    if let lastNewOperation = lastNewOp?.takeUnretainedValue() {
                        lastNewOperation.__nextOperation = retained
                    } else {
                        firstNewOp = retained
                    }
                    lastNewOp = retained
                } else {
                   // 前面的任务状态有修改失败的场景,回滚当前任务的状态修改
                    _ = op._compareAndSwapState(.enqueuing, .initialized)
                }
            } else {
                // 如果修改失败,失败数累加1
                failures += 1
            }
        }
        
        // 判断是否有任务入队失败
        if 0 < failures {

            // 因为有失败情况发生,要回滚前面的操作,firstNewOp就是双向链表的头节点
            while let firstNewOperation = firstNewOp?.takeUnretainedValue() {
                // 取出下一个节点
                let nextNewOp = firstNewOperation.__nextOperation
                // 对当前任务对象做重置操作
                firstNewOperation._invalidateQueue()
                // 清理链接节点指针
                firstNewOperation.__previousOperation = nil
                firstNewOperation.__nextOperation = nil
                // 回滚任务的状态
                _ = firstNewOperation._compareAndSwapState(.enqueuing, .initialized)
                // 释放任务
                firstNewOp?.release()
                // 继续处理后继节点
                firstNewOp = nextNewOp
            }

            // 回滚完,还是要报fatalError
            fatalError("operations finished, executing or already in a queue cannot be enqueued")
        }
        
        // Attach any operations pending attachment to main list
        
        // 非阻塞任务
        if !barrier {
            // 加锁,因为后续要修改OperationQueue的成员变量
            _lock()
            // OperationCount自增1,这里自增1不是很对啊
            _incrementOperationCount()
        }
        
        // 前面已经处理好任务的状态,并生成了一个双向链表
        // firstNewOp就是链表头,lastNewOp就是链表最后一个元素
        // __firstOperation和__lastOperation是OperationQueue已经存在的双向链表
        // 这里是要把此次传入的任务链表,挂到OperationQueue的双向链表上去
        var pending = firstNewOp
        if let pendingOperation = pending?.takeUnretainedValue() {
            let old_last = __lastOperation
            pendingOperation.__previousOperation = old_last
            if let old = old_last?.takeUnretainedValue() {
                old.__nextOperation = pending
            } else {
                __firstOperation = pending
            }
            __lastOperation = lastNewOp
        }

        // pending就是firstNewOp,是链表表头,这里就是循环处理任务链表
        while let pendingOperation = pending?.takeUnretainedValue() {
            if !barrier {
                // 如果任务中有要阻塞的barrie任务,是通过把它添加到依赖任务中,来实现的
                var barrierOp = _firstPriorityOperation(Operation.QueuePriority.barrier)
                while let barrierOperation = barrierOp?.takeUnretainedValue() {
                    pendingOperation._addDependency(barrierOperation)
                    barrierOp = barrierOperation.__nextPriorityOperation
                }
            }
            
            // 任务的状态从enqueuing改成enqueued
            _ = pendingOperation._compareAndSwapState(.enqueuing, .enqueued)

            // 根据__priorityValue和__propertyQoS设置一下任务的优先级
            // 如果未设置过优先级,默认是Operation.QueuePriority.normal级别
            var pri = pendingOperation.__priorityValue
            if pri == nil {
                let v = __actualMaxNumOps == 1 ? nil : pendingOperation.__propertyQoS
                if let qos = v {
                    switch qos {
                    case .default: pri = Operation.QueuePriority.normal.rawValue
                    case .userInteractive: pri = Operation.QueuePriority.veryHigh.rawValue
                    case .userInitiated: pri = Operation.QueuePriority.high.rawValue
                    case .utility: pri = Operation.QueuePriority.low.rawValue
                    case .background: pri = Operation.QueuePriority.veryLow.rawValue
                    }
                } else {
                    pri = Operation.QueuePriority.normal.rawValue
                }
            }

            // 按照任务的优先级,还有一个单链表,链表节点字段是Operation的__nextPriorityOperation
            // 单链表的头节点和尾节点是OperationQueue的__firstPriorityOperation和__lastPriorityOperation
            // 它俩是元组对象,包含所有级别的单链表的头节点和尾节点
            pendingOperation.__nextPriorityOperation = nil
            if let old_last = _lastPriorityOperation(pri)?.takeUnretainedValue() {
                old_last.__nextPriorityOperation = pending
            } else {
                _setFirstPriorityOperation(pri!, pending)
            }
            _setlastPriorityOperation(pri!, pending)

            // 循环下一个链表
            pending = pendingOperation.__nextOperation
        }
        
        // 非阻塞任务
        if !barrier {
            // 解锁,任务添加完毕
            _unlock()
        }
        
        // 阻塞任务由调用方实现调度逻辑
        if !barrier {
            // 调度任务
            _schedule()
        }
    }
}

调度任务

internal func _schedule() {

        // 重试任务数组
        var retestOps = [Operation]()

        // 因为要对OperationQueue操作,所以要先加锁
        _lock()

        // 可用的槽位数
        var slotsAvail = __actualMaxNumOps - __numExecOps

        // 要循环一下优先级单链表上的任务
        for prio in Operation.QueuePriority.priorities {

            // 如果没有可用的槽位,或者当前任务队列被暂停,则跳出循环
            if 0 >= slotsAvail || _suspended {
                break
            }

            // 根据任务优先级获取任务优先级单链表的表头
            var op = _firstPriorityOperation(prio)

            // 前驱节点,移除当前节点的时候要使用
            var prev: Unmanaged<Operation>?
            while let operation = op?.takeUnretainedValue() {

                // 保护判断一下
                if 0 >= slotsAvail || _suspended {
                    break
                }

                // 后继节点
                let next = operation.__nextPriorityOperation

                // 是否要重试
                var retest = false

                // if the cached state is possibly not valid then the isReady value needs to be re-updated
                // 如果任务状态已经是enqueued,并且没有未完成的依赖,则开始执行此任务
                if Operation.__NSOperationState.enqueued == operation._state && operation._fetchCachedIsReady(&retest) {
                    
                    // 从任务优先级单链表上移除此任务
                    if let previous = prev?.takeUnretainedValue() {
                        previous.__nextPriorityOperation = next
                    } else {
                        _setFirstPriorityOperation(prio, next)
                    }
                    if next == nil {
                        _setlastPriorityOperation(prio, prev)
                    }
                    
                    // 已经从单链表上移除,清空后继节点
                    operation.__nextPriorityOperation = nil
                    
                    // 状态修改成dispatching
                    operation._state = .dispatching

                    // __numExecOps自增1
                    _incrementExecutingOperations()

                    // 可用的槽位数减1
                    slotsAvail -= 1
                    
                    // 选择GCD的Queue
                    let queue: DispatchQueue
                    if __mainQ {
                        // 如果是主线程,则使用主线程的GCD的Queue
                        queue = DispatchQueue.main
                    } else {
                        // 如果未设置__dispatch_queue,会根据QoS合成一个对应的GCD DispatchQueue
                        queue = __dispatch_queue ?? _synthesizeBackingQueue()
                    }
                    
                    // 取出任务的GCD工作对象
                    if let schedule = operation.__schedule {
                        if operation is _BarrierOperation {
                            // 如果是Barrier阻塞任务,则调用GCD的时候也设置barrier参数
                            queue.async(flags: .barrier, execute: {
                                schedule.perform()
                            })
                        } else {
                            // 异步执行任务
                            queue.async(execute: schedule)
                        }
                    }
                    
                    // 处理后续任务
                    op = next
                } else {
                    // 如果任务还未准备好
                    if retest {
                        // 放到重试数组中
                        retestOps.append(operation)
                    }
                    // 继续循环后续任务
                    prev = op
                    op = next
                }
            }
        }
        // 解锁
        _unlock()
        
        // 尝试重新计算未准备好的任务的ready状态
        for op in retestOps {
            if op.isReady {
                op._cachedIsReady = true
            }
        }
    }

DispatchWorkItem的block会执行OperationQueue的_schedule(_ op: Operation)方法,就是下面这个方法,这个block是_addOperations的时候设置的

internal func _schedule(_ op: Operation) {

    // 设置任务状态为starting
    op._state = .starting

    // set current tsd
    // 这样设置以后,在当前线程中的start方法可以找到OperationQueue的引用,Operation没有对外暴露其引用
    // 就是OperationQueue.current
    OperationQueue._currentQueue.set(self)

    // 开始执行Operation的start方法
    op.start()

    // 重置currentQueue
    OperationQueue._currentQueue.clear()

    // We've just cleared _currentQueue storage.
    // NSThreadSpecific doesn't release stored value on clear.
    // This means `self` will leak if we don't release manually.
    Unmanaged.passUnretained(self).release()
    
    // 如果任务的isFinished返回YES,但是状态还不是finished,触发一下KVO,结束当前任务
    // 这个属于补偿逻辑,一般设置了finished = YES,按理说就应该触发其KVO
    // unset current tsd
    if op.isFinished && op._state.rawValue < Operation.__NSOperationState.finishing.rawValue {
        Operation.observeValue(forKeyPath: _NSOperationIsFinished, ofObject: op)
    }
}

执行任务

在同步模式的时候,还有一个_execute方法会执行

internal func _execute(_ op: Operation) {
    // 同步模式可以反馈任务进度
    var operationProgress: Progress? = nil
    if !(op is _BarrierOperation) && _isReportingProgress {
        let opProgress = Progress(parent: nil, userInfo: nil)
        opProgress.totalUnitCount = 1
        progress.addChild(opProgress, withPendingUnitCount: 1)
        operationProgress = opProgress
    }
    operationProgress?.becomeCurrent(withPendingUnitCount: 1)
    defer { operationProgress?.resignCurrent() }
    
    // 执行任务的main方法
    op.main()
}

结束任务

internal func _operationFinished(_ op: Operation, _ previousState: Operation.__NSOperationState) {
    // There are only three cases where an operation might have a nil queue
    // A) The operation was never added to a queue and we got here by a normal KVO change
    // B) The operation was somehow already finished
    // C) the operation was attempted to be added to a queue but an exception occured and was ignored...
    // Option C is NOT supported!

    // 判断任务是否是阻塞任务
    let isBarrier = op is _BarrierOperation

    // 加锁
    _lock()

    // 取后续任务,移除链表的时候要使用
    let nextOp = op.__nextOperation

    // 判断任务状态是否已结束
    if Operation.__NSOperationState.finished == op._state {

        // 任务已执行完,讲任务移除链表
        let prevOp = op.__previousOperation
        if let prev = prevOp {
            prev.takeUnretainedValue().__nextOperation = nextOp
        } else {
            __firstOperation = nextOp
        }
        if let next = nextOp {
            next.takeUnretainedValue().__previousOperation = prevOp
        } else {
            __lastOperation = prevOp
        }
        // only decrement execution count on operations that were executing! (the execution was initially set to __NSOperationStateDispatching so we must compare from that or later)
        // else the number of executing operations might underflow

        // 减少正在执行的任务数
        if previousState.rawValue >= Operation.__NSOperationState.dispatching.rawValue {
            _decrementExecutingOperations()
        }

        // 重置任务的前后链表节点
        op.__previousOperation = nil
        op.__nextOperation = nil

        // 重置任务队列
        op._invalidateQueue()
    }

    // 减少任务数
    if !isBarrier {
        _decrementOperationCount()
    }

    // 解锁
    _unlock()
    
    // 在调度一下其他任务
    _schedule()
    
    // 释放任务
    if previousState.rawValue >= Operation.__NSOperationState.enqueuing.rawValue {
        Unmanaged.passUnretained(op).release()
    }
}

Operation

任务状态

Operation有一个__state成员变量,表示当前任务状态,__NSOperationState枚举有8个值,初始化的时候initialized,每次对__state状态修改,都有__atomicLoad锁来保护。

open class Operation : NSObject {
    // 任务状态枚举
    enum __NSOperationState : UInt8 {
        case initialized = 0x00
        case enqueuing = 0x48
        case enqueued = 0x50
        case dispatching = 0x88
        case starting = 0xD8
        case executing = 0xE0
        case finishing = 0xF0
        case finished = 0xF4
    }

    // 任务状态
    internal var __state: __NSOperationState = .initialized
    // 负责同步任务状态的锁
    var __atomicLoad = NSLock()

    // 任务状态的get和set方法都由__atomicLoad来同步
    internal var _state: __NSOperationState {
        get {
            __atomicLoad.lock()
            defer { __atomicLoad.unlock() }
            return __state
        }
        set(newValue) {
            __atomicLoad.lock()
            defer { __atomicLoad.unlock() }
            __state = newValue
        }
    }
    
    // CAS方法,用来修改任务状态
    internal func _compareAndSwapState(_ old: __NSOperationState, _ new: __NSOperationState) -> Bool {
        __atomicLoad.lock()
        defer { __atomicLoad.unlock() }
        if __state != old { return false }
        __state = new
        return true
    }
}

初始化 

Operation的init方法是一个空实现,子类实现的时候可以重载init方法,带一些业务数据字段,将来可以在start方法中使用,比如,下载的链接地址NSURL对象。

open class Operation : NSObject {
    public override init() { }
}

start

OperationQueue调度任务执行的时候,最终会执行任务的start方法,如果是异步模式,子类是要覆写start方法的,如果是同步模式,start方法不用动,start方法内部最终会调用main方法。

open func start() {
    let state = _state

    // 判断一下任务的状态,如果已经结束就直接返回
    if __NSOperationState.finished == state { return }

    // 判断任务是否是重复执行
    if !_compareAndSwapState(__NSOperationState.initialized, __NSOperationState.starting) && !(__NSOperationState.starting == state && __queue != nil) {
        switch state {
        case .executing: fallthrough
        case .finishing:
            fatalError("(self): receiver is already executing")
        default:
            fatalError("(self): something is trying to start the receiver simultaneously from more than one thread")
        }
    }
    
    // 任务状态是已入队,但是还没有ready,就开始执行,也要报错
    if state.rawValue < __NSOperationState.enqueued.rawValue && !isReady {
        _state = state
        fatalError("(self): receiver is not yet ready to execute")
    }
    
    // 判断任务是否已取消
    let isCanc = _isCancelled
    if !isCanc {

        // 任务未取消,状态改成executing开始执行
        _state = .executing
        Operation.observeValue(forKeyPath: _NSOperationIsExecuting, ofObject: self)
        
        // 如果任务放到了队列中,就调用队列的_execute方法,否则直接执行main方法
        _queue?._execute(self) ?? main()
    }
    
    // 结束任务
    if __NSOperationState.executing == _state {
        _state = .finishing
        Operation.observeValue(forKeyPath: _NSOperationIsExecuting, ofObject: self)
        Operation.observeValue(forKeyPath: _NSOperationIsFinished, ofObject: self)
    } else {
        _state = .finishing
        Operation.observeValue(forKeyPath: _NSOperationIsFinished, ofObject: self)
    }
}

KVO监控处理

internal static func observeValue(forKeyPath keyPath: String, ofObject op: Operation) {
    enum Transition {
        case toFinished
        case toExecuting
        case toReady
    }
    
    // 根据keyPath来设置kind
    let kind: Transition?
    if keyPath == _NSOperationIsFinished || keyPath == _NSOperationIsFinishedAlternate {
        kind = .toFinished
    } else if keyPath == _NSOperationIsExecuting || keyPath == _NSOperationIsExecutingAlternate {
        kind = .toExecuting
    } else if keyPath == _NSOperationIsReady || keyPath == _NSOperationIsReadyAlternate {
        kind = .toReady
    } else {
        kind = nil
    }
    if let transition = kind {
        switch transition {
        case .toFinished: // we only care about NO -> YES
            // 触发了isFinished KVO
            if !op.isFinished {
                // 误触发,isFinished返回NO,先返回
                return
            }
            
            // 以及ready的依赖任务
            var ready_deps = [Operation]()
            op._lock()
            let state = op._state

            // 打印警告信息,任务还未开始执行,就已经设置了isFinished KVO
            if op.__queue != nil && state.rawValue < __NSOperationState.starting.rawValue {
                print("*** (type(of: op)) (Unmanaged.passUnretained(op).toOpaque()) went isFinished=YES without being started by the queue it is in")
            }
            if state.rawValue < __NSOperationState.finishing.rawValue {
                op._state = .finishing
            } else if state == .finished {
                op._unlock()
                return
            }
            let down_deps = op.__downDependencies
            op.__downDependencies.removeAll()
            if 0 < down_deps.count {
                for down in down_deps {
                    let idown = down.contents.takeUnretainedValue()
                    idown._lock()
                    if idown._unfinishedDependencyCount == 1 {
                        ready_deps.append(idown)
                    } else if idown._unfinishedDependencyCount > 1 {
                        idown._decrementUnfinishedDependencyCount()
                    } else {
                        assert(idown._unfinishedDependencyCount  == 0)
                        assert(idown._isCancelled == true)
                    }
                    idown._unlock()
                }
            }
            
            // 任务结束,修改状态
            op._state = .finished

            // 重置任务队列引用
            let oq = op.__queue
            op.__queue = nil

            // 是否任务锁
            op._unlock()
            
            if 0 < ready_deps.count {
                for down in ready_deps {
                    down._lock()
                    if down._unfinishedDependencyCount >= 1 {
                        down._decrementUnfinishedDependencyCount()
                    }
                    down._unlock()
                    Operation.observeValue(forKeyPath: _NSOperationIsReady, ofObject: down)
                }
            }
            
            // waitUntilFinished方法可以返回了
            op.__waitCondition.lock()
            op.__waitCondition.broadcast()
            op.__waitCondition.unlock()

            // 如果设置__completion回调,这异步执行一下回调
            if let complete = op.__completion {
                let held = Unmanaged.passRetained(op)
                DispatchQueue.global(qos: .default).async {
                    complete()
                    held.release()
                }
            }

            // 从任务队列中移除已经完成的任务
            if let queue = oq {
                queue.takeUnretainedValue()._operationFinished(op, state)
                queue.release()
            }
        case .toExecuting:
            let isExecuting = op.isExecuting
            op._lock()
            // 更新状态为正在执行
            if op._state.rawValue < __NSOperationState.executing.rawValue && isExecuting {
                op._state = .executing
            }
            op._unlock()
        case .toReady:
            // 任务已经ready,调度执行一下任务
            let r = op.isReady
            op._cachedIsReady = r
            let q = op._queue
            if r {
                q?._schedule()
            }
        }
    }
}

总结

以上就是Operation的核心处理流程,通读一遍源代码,对理解Operation Queue有非常大的帮助。