OperationQueue与属性maxConcurrentOperationCount的那些事

系统: Mac OS 10.14.6, XCode 11,swift 5.0
写作时间:2019-11-17

说明

Alamofire 5.0中的Session设置了maxConcurrentOperationCount = 1, 代码如下

public convenience init(configuration: URLSessionConfiguration = URLSessionConfiguration.af.default,
                        delegate: SessionDelegate = SessionDelegate(),
                        rootQueue: DispatchQueue = DispatchQueue(label: "org.alamofire.session.rootQueue"),
                        startRequestsImmediately: Bool = true,
                        requestQueue: DispatchQueue? = nil,
                        serializationQueue: DispatchQueue? = nil,
                        interceptor: RequestInterceptor? = nil,
                        serverTrustManager: ServerTrustManager? = nil,
                        redirectHandler: RedirectHandler? = nil,
                        cachedResponseHandler: CachedResponseHandler? = nil,
                        eventMonitors: [EventMonitor] = []) {
    precondition(configuration.identifier == nil, "Alamofire does not support background URLSessionConfigurations.")

    let delegateQueue = OperationQueue(maxConcurrentOperationCount: 1, underlyingQueue: rootQueue, name: "org.alamofire.session.sessionDelegateQueue")
    let session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: delegateQueue)

    self.init(session: session,
              delegate: delegate,
              rootQueue: rootQueue,
              startRequestsImmediately: startRequestsImmediately,
              requestQueue: requestQueue,
              serializationQueue: serializationQueue,
              interceptor: interceptor,
              serverTrustManager: serverTrustManager,
              redirectHandler: redirectHandler,
              cachedResponseHandler: cachedResponseHandler,
              eventMonitors: eventMonitors)
}

今天就聊聊这个设置的作用和实验。maxConcurrentOperationCount = 1 表示同一时间只能处理一个任务Operation, 那么它是同步操作么,下面下个例子把当前线程的信息打印出来就知道了。

maxConcurrentOperationCount的值设为1,可以看作该队列为串行队列,每次只能执行一个任务。不过NSOPerationQueue不是先进先出(FIFO)队列,这点跟dispatch queue有点区别,dispatch queue中的block会按照FIFO的顺序去执行,NSOPerationQueue会根据Operation的状态(是否Ready)以及优先级来确定执行的NSOperation的顺序。

例子

func operationQueueDemo1() {
    let queue = OperationQueue()
    queue.maxConcurrentOperationCount = 1
    queue.addOperation {
        print("first mission, current thread is : \(Thread.current)")
    }
    queue.addOperation {
        print("second mission, current thread is : \(Thread.current)")
    }
    queue.addOperation {
        print("third mission, current thread is : \(Thread.current)")
    }
    let blockOperationOne = BlockOperation.init {
        print("fisrt block mission, current thread is : \(Thread.current)")
    }
    blockOperationOne.queuePriority = .veryLow
    let blockOperationTwo = BlockOperation.init {
        print("second block mission, current thread is : \(Thread.current)")
    }
    blockOperationTwo.queuePriority = .veryHigh
    let blockOperationDependency = BlockOperation.init {
        print("dependency block mission, current thread is : \(Thread.current)")
    }
    blockOperationTwo.addDependency(blockOperationDependency)
    
    queue.addOperation(blockOperationOne)
    queue.addOperation(blockOperationTwo)
    queue.addOperation(blockOperationDependency)
}

控制台输出:

first mission, current thread is : <NSThread: 0x600002dd4480>{number = 3, name = (null)}
second mission, current thread is : <NSThread: 0x600002dc0bc0>{number = 5, name = (null)}
third mission, current thread is : <NSThread: 0x600002dc0bc0>{number = 5, name = (null)}
dependency block mission, current thread is : <NSThread: 0x600002dc0bc0>{number = 5, name = (null)}
second block mission, current thread is : <NSThread: 0x600002dc0bc0>{number = 5, name = (null)}
fisrt block mission, current thread is : <NSThread: 0x600002dd4480>{number = 3, name = (null)}

如果注释掉blockOperationTwo.addDependency(blockOperationDependency), 那么执行顺序会变成first mission > second block mission > second mission > third mission > first block mission. 再次强调一下:NSOPerationQueue不是先进先出(FIFO)队列,这点跟dispatch queue有点区别,dispatch queue中的block会按照FIFO的顺序去执行,NSOPerationQueue会根据Operation的状态(是否Ready)以及优先级来确定执行的NSOperation的顺序。

结论

从上面的运行结果发现,有dependency的线程地址是同一个(dependency block和second block),fisrt block有事单独的一个,所以maxConcurrentOperationCount = 1 表示同一时间只有一个任务在执行,但是不表示只有一个线程在执行。

你可能感兴趣的:(iOS)