1. 程式人生 > >https://www.jianshu.com/p/fc78dab5736f

https://www.jianshu.com/p/fc78dab5736f

semaphore attribute 完成後 iat ping program targe width gcd

在學習Swift 3的過程中整理了一些筆記,如果想看其他相關文章可前往《Swift 3必看》系列目錄

swift 3中對C層級的GCD的API進行了徹頭徹尾的改變。本文將從實際使用場景來了解一下新的api使用。

dispatch_async

一個常見的場景就是在一個全局隊列進行一些操作後切換到主線程配置UI。現在是這麽寫:

DispatchQueue.global().async {
    // code
    DispatchQueue.main.async {
        // 主線程中
    }
}

global()是一個有著默認參數的靜態函數:

class DispatchQueue : DispatchObject {
    public  class var main: DispatchQueue 
    public class func global(qos: DispatchQoS.QoSClass = default) -> DispatchQueue
}

sync

如果想同步執行操作,和async類似,調用sync就可以了:

DispatchQueue.global().sync {
    // 同步執行
}

優先級:DispatchQoS

我們知道,GCD 的默認隊列優先級有四個:

  • DISPATCH_QUEUE_PRIORITY_HIGH
  • DISPATCH_QUEUE_PRIORITY_DEFAULT
  • DISPATCH_QUEUE_PRIORITY_LOW
  • DISPATCH_QUEUE_PRIORITY_BACKGROUND

現在則改為了QoSClass枚舉

 public enum QoSClass {

        case background

        case utility

        case `default`

        case userInitiated

        case userInteractive

        case unspecified

        public init?(rawValue: qos_class_t)

        public var rawValue: qos_class_t { get }
    }

這些命名比原先的更加友好,能更好表達這個操作的意圖。

技術分享圖片

和原有的對應關系是:

* DISPATCH_QUEUE_PRIORITY_HIGH:         .userInitiated
* DISPATCH_QUEUE_PRIORITY_DEFAULT:      .default
* DISPATCH_QUEUE_PRIORITY_LOW:          .utility
* DISPATCH_QUEUE_PRIORITY_BACKGROUND:   .background

創建隊列

DispatchQueue的默認初始化方法創建的就是一個同步隊列,如果要創建並發的隊列,在attributes中聲明concurrent。

// 同步隊列
let serialQueue = DispatchQueue(label: "queuename")

// 並發隊列
let concurrentQueue = DispatchQueue(label: "queuename", attributes: .concurrent)

推遲時間後執行

原先的dispatch_time_t現在由DispatchTime對象表示。可以用靜態方法now獲得當前時間,然後再通過加上一個DispatchTimeInterval枚舉來獲得一個需要延遲的時間。

let delay = DispatchTime.now() + DispatchTimeInterval.seconds(60)
DispatchQueue.main.asyncAfter(deadline: delay) { 
    // 延遲執行
}

這裏也可以直接加上一個秒數。

let three = DispatchTime.now() + 3.0

因為DispatchTime中自定義了<code>+</code>號。


public func +(time: DispatchTime, seconds: Double) -> DispatchTime

DispatchGroup

如果想在dispatch_queue中所有的任務執行完成後再做某種操作可以使用DispatchGroup。原先的dispatch_group_t由現在的DispatchGroup對象代替。

let group = DispatchGroup()

let queueBook = DispatchQueue(label: "book")
queueBook.async(group: group) {
    // 下載圖書
}
let queueVideo = DispatchQueue(label: "video")
queueVideo.async(group: group) {
    // 下載視頻
}

group.notify(queue: DispatchQueue.main) { 
    // 下載完成
}

DispatchGroup會在組裏的操作都完成後執行notify。
如果有多個並發隊列在一個組裏,我們想在這些操作執行完了再繼續,調用wait

group.wait()

DispatchWorkItem

使用DispatchWorkItem代替原來的<code>dispatch_block_t</code>。
在DispatchQueue執行操作除了直接傳了一個<code>() -> Void</code>類型的閉包外,還可以傳入一個DispatchWorkItem。


    public func sync(execute workItem: DispatchWorkItem)

    public func async(execute workItem: DispatchWorkItem)

DispatchWorkItem的初始化方法可以配置Qos和DispatchWorkItemFlags,但是這兩個參數都有默認參數,所以也可以只傳入一個閉包。

    public init(qos: DispatchQoS = default, flags: DispatchWorkItemFlags = default, block: @escaping @convention(block) () -> ())

let workItem = DispatchWorkItem { 
    // TODO:
}

DispatchWorkItemFlags枚舉中assignCurrentContext表示QoS根據創建時的context決定。
值得一提的是DispatchWorkItem也有wait方法,使用方式和group一樣。調用會等待這個workItem執行完。

let myQueue = DispatchQueue(label: "my.queue", attributes: .concurrent)
let workItem = DispatchWorkItem {
    sleep(1)
    print("done")
}
myQueue.async(execute: workItem)
print("before waiting")
workItem.wait()
print("after waiting")

barrier

假設我們有一個並發的隊列用來讀寫一個數據對象。如果這個隊列裏的操作是讀的,那麽可以多個同時進行。如果有寫的操作,則必須保證在執行寫入操作時,不會有讀取操作在執行,必須等待寫入完成後才能讀取,否則就可能會出現讀到的數據不對。在之前我們用dipatch_barrier實現。
現在屬性放在了DispatchWorkItemFlags裏。

let wirte = DispatchWorkItem(flags: .barrier) { 
    // write data
}
let dataQueue = DispatchQueue(label: "data", attributes: .concurrent)
dataQueue.async(execute: wirte)

信號量

為了線程安全的統計數量,我們會使用信號量作計數。原來的dispatch_semaphore_t現在用DispatchSemaphore對象表示。
初始化方法只有一個,傳入一個Int類型的數。


let semaphore = DispatchSemaphore(value: 5)

 // 信號量減一
semaphore.wait()

 //信號量加一
semaphore.signal()

dispatch_once被廢棄

在swift 3中已經被廢棄了。
簡單的建議就是一些初始化場景就用懶加載吧。

// Examples of dispatch_once replacements with global or static constants and variables. 
// In all three, the initialiser is called only once. 

// Static properties (useful for singletons).
class Object {
    static let sharedInstance = Object()
}

// Global constant.
let constant = Object()

// Global variable.
var variable: Object = {
    let variable = Object()
    variable.doSomething()
    return variable
}()

歡迎關註我的微博:@沒故事的卓同學

相關鏈接:
SE0088-Modernize libdispatch for Swift 3 naming conventions
Concurrent Programming With GCD in Swift 3



作者:沒故事的卓同學
鏈接:https://www.jianshu.com/p/fc78dab5736f
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並註明出處。

https://www.jianshu.com/p/fc78dab5736f