iOS多線程簡介 - Swift版本 1.多線程開發 -- CGD的簡單使用

在咱們實際開發中, 有不免會遇到一些問題, 好比我要從網上下載一張圖片進行修改, 這裏就涉及到線程的問題了, 還有就是咱們日常使用的下載工具: 迅雷, QQ旋風之類的, 它們能夠進行同時下載, 也能夠一個一個的來下載, 在這裏咱們稱之爲同步和異步, 顧名思義, 所謂的同步就是全部文件一塊兒下載, 異步就是把須要下載的文件一個個排好隊來下載.程序員


1.基本概念

在開始說多線程以前, 咱們要知道兩樣東西, 一個是進程, 一個是線程:面試

進程: 正在進行中的程序就叫作進程, 負責程序運行的內存分配, 每個進程都有本身獨立的虛擬內存空間.編程

線程: 線程是進程中一個獨立的執行路徑(控制單元), 一個進程中至少包含一條線程(主線程), 能夠將耗時的操做或者執行放到另外一個線程裏.後端

說白了, 進程就是爲程序分配內存的, 而線程就是用來控制程序代碼的實際運行.安全

舉個例子, 咱們的程序運行, 都是按照代碼從上往下的執行, 但若是遇到須要下載圖片的時候, 它就會卡在這裏, 等待圖片下載完成纔會執行下一步, 這樣子就不符合咱們的實際體驗了, 因此咱們會把下載圖片放到子線程裏去操做, 等到下載完成以後才傳回給主線程, 這就是多線程的好處, 既不會影響主線程的運行, 又能夠完成下載圖片的任務.markdown

提示:
1.dispatch_async 異步操做,會併發執⾏,沒法肯定任務的執⾏順序
2.dispatch_sync 同步操做,會依次順序執⾏,可以決定任務的執行順序多線程

PS: 線程是有限的, 不能夠無休止的增長, 而主線程的大小隻有1MB, 子線程都是512KB.併發


2.GCD隊列

串行隊列: 隊列中的任務只會順序執⾏異步

func gcdDemo1() {
        // 將操做放在隊列中
        // 在 C 語言函數中, 定義類型, 絕大多數都是以_t或者ref 結尾
        // 使用串行隊列的異步任務, 能夠節省資源, 新建線程是須要有資源消耗的, 不能無休止的去新建線程

        // 應用案例:
        // 從網上下載圖片
        // 濾鏡(高光, 紅眼...)
        var q: dispatch_queue_t = dispatch_queue_create("com.cain.gcdDemo1", DISPATCH_QUEUE_SERIAL)
        let i = 0

        for i in 0...10 {
            dispatch_async(q, { () -> Void in
                println(NSThread.currentThread())
            })
        }
        // 非 ARC 開發時, 必定要 release
        // dispatch_release(q);

        // 串行隊列的同步任務, 也會在主線程中運行
        // 在實際開發中, 極少人用
        // 面試又可能會用到
        for i in 0...9 {
            // 同步任務, 順序執行
            dispatch_async(q, { () -> Void in
                println("\(NSThread.currentThread()) - \(i)")
            })
        }
    }

並行隊列: 隊列中的任務一般會併發執⾏async

func gcdDemo2() {
        // 特色: 沒有順序, 程序員不可控
        // 應用場景: 併發執行的, 沒有前後順序
        // 並行隊列容易出錯, 並行隊列建立的子線程數量一樣是不可控
        var q: dispatch_queue_t = dispatch_queue_create("com.cain.gcdDemo2", DISPATCH_QUEUE_CONCURRENT)

        for i in 0...9 {
            // 同步任務
            dispatch_sync(q, { () -> Void in
                println("\(NSThread.currentThread()) - \(i)")
            })
            // 異步任務
            dispatch_async(q, { () -> Void in
                // [NSThread currentThread] 能夠在開發中跟蹤當前的線程.
                // number = 1表示主線程
                // number = 2或者其餘, 表示子線程, 這裏是2, 因此是第2個子線程
                println("\(NSThread.currentThread()) - \(i)")
            })
        }
    }

全局隊列

func gcdDemo3() {
        // 全局隊列與並行隊列的區別
        // 1< 不須要建立, 直接GET就可使用
        // 2< 兩個隊列的執行效果相同
        // 3< 全局隊列沒有名稱, 調試時沒法確認準確隊列
        var q: dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
        for i in 0...9 {
            // 異步任務
            dispatch_async(q, { () -> Void in
                println("\(NSThread.currentThread()) - \(i)")
            })
            // 同步任務
            dispatch_sync(q, { () -> Void in
                println("\(NSThread.currentThread()) - \(i)")
            })
        }
    }

主線程隊列

func gcdDemo4() {
        var q = dispatch_get_main_queue()
        for i in 0...9 {
            // 異步任務, 併發執行, 保持隊形的
            dispatch_async(q, { () -> Void in println("\(NSThread.currentThread()) - \(i)") }); // 同步任務 // 注意, 在主線程隊列中不可使用同步任務, 不然會形成線程阻塞 // dispatch_sync(q, { () -> Void in // println("come here baby!") // }); } }

3.GCD總結

串⾏隊列
1.同步任務, 不須要新建線程, 異步任務, 須要⼀個⼦線程, 線程的建立和回收不須要程序員參與!
2.「是最安全的一個選擇」串⾏行隊列只能建立!

並行隊列
1.同步任務, 不須要建立線程並行隊列, 異步任務, 有多少個任務, 就開N個線程執⾏行 不管什麼隊列和什麼任務, 線程的建立和回收不須要程序員參與.

2.線程的建立回收⼯做是由隊列負責的 「併發」編程, 爲了讓程序員從負責的線程控制中解脫出來! 只須要⾯對隊列和任務!

GCD的好處
1.經過GCD, 開發者不⽤再直接跟線程打交道, 只須要向隊列中添加代碼塊便可.

2.GCD在後端管理着⼀個線程池, GCD不只決定着代碼塊將在哪一個線程被執⾏, 它還根據可用的系統資源對這些線程進⾏管理. 從而讓開發者從線程管理的工做中解放出來, 經過集中的管理線程, 緩解大量線程被建立的問題.

3.使⽤用GCD, 開發者能夠將工做考慮爲一個隊列, 而不是一堆線程,這種並行的抽象模型更容易掌握和使⽤.

GCD的隊列
1.GCD公開有5個不一樣的隊列: 運⾏在主線程中的主隊列, 3個不一樣優先級的後臺隊列, 以及一個優先級更低的後臺隊列(⽤於 I/O).

2.⾃定義隊列: 串⾏行和並⾏行隊列, ⾃定義隊列⾮常強大,建議在開發中使⽤, 在⾃定義隊列中被調度的全部Block最終都將被放⼊到系統的全局隊列中和線程池中.

提示: 不建議使⽤用不一樣優先級的隊列, 由於若是設計不當, 可能會出現優先級反轉, 即低優先級的操做阻塞⾼優先級的操做.


好了, 此次咱們就講到這裏, 下次咱們繼續~~

相關文章
相關標籤/搜索