Swift- 多線程編程GCD

參考文章:
1、Swift 3使用GCD和DispatchQueues

2、線程死鎖

基本概念:

串行隊列:只有一個線程,加入到隊列中的操作按添加順序依次執(zhí)行。并且還要保證在執(zhí)行某個任務時,在它前面進入隊列的所有任務肯定執(zhí)行完了。對于每一個不同的串行隊列,系統(tǒng)會為這個隊列建立唯一的線程來執(zhí)行代碼。

并發(fā)隊列:這個隊列中的任務也是按照先來后到的順序開始執(zhí)行,注意是開始,但是它們的執(zhí)行結(jié)束時間是不確定的,取決于每個任務的耗時。對于n個并發(fā)隊列,GCD不會創(chuàng)建對應的n個線程而是進行適當?shù)膬?yōu)化

同步執(zhí)行:會阻塞當前線程 sync默認會在當前線程執(zhí)行(系統(tǒng)優(yōu)化)

異步執(zhí)行:異步添加任務

1、主隊列和全局隊列

全局隊列(可以設置服務等級(Qos class))

DispatchQueue.global().async {
  //主隊列
  DispatchQueue.main.async {
   
  } 
}

ps:蘋果為了優(yōu)化性能, sync會盡可能在當前線程來運行

ps:主線程|當前線程

print(Thread.main,Thread.current,Thread.isMainThread)

2、隊列的優(yōu)先級

.userInteractive
.userInitiated
.default
.utility
.background
.unspecified

3、并發(fā)隊列(Concurrent Queues)

1、隊列默認就是串行執(zhí)行的(serial)

//創(chuàng)建并行隊列
let anotherQueue = DispatchQueue(label:"com.appcoda.anotherQueue",qos:.utility,attributes: .concurrent)

2、通過定義為initiallyInactive 隊列任務不會自動開始執(zhí)行,需要開發(fā)者主動去觸發(fā)

let anotherQueue2 = DispatchQueue(label:"com.appcoda.anotherQueue2", 
qos: .utility,attributes[.concurrent,.initiallyInactive]) 
 //手動觸發(fā)
 if let queue = inactiveQueue {
            queue.activate()
         }
         
PS:         
//Suspend可以掛起一個線程,就是把這個線程暫停了,它占著資源,但不運行,
//用Resume是繼續(xù)掛起的線程,讓這個線程繼續(xù)執(zhí)行下去 
  anotherQueue2.resume()
  anotherQueue2.suspend(        
  

4、延遲執(zhí)行

let delay = DispatchTime.now() + .seconds(60)
DispatchQueue.main. asyncAfter(when: delay) {
 // Do something
}

OC的實現(xiàn)

let dispatch_time = dispatch_time(DISPATCH_TIME_NOW, Int64(60 * NSEC_PER_SEC))
/*
是當前事前, 然后加上 .seconds(60) 代表 60秒。 
再使用 DispatchQueue.main.after 
讓這個操作在 60 秒后執(zhí)行
*/
DispatchTime.now() 


5、DispatchWorkItem對象

let workItem = DispatchWorkItem {
    //代碼塊
  }
let queue = Dispatchqueue.global()
//默認在主隊列執(zhí)行(下面是全局隊列執(zhí)行)
queue.async {
    workItem.perform()
}

//執(zhí)行完成后通知
workItem.notify(queue: Dispatchqueue.main) {
       
    }

6、DispatchGroup

隊列組

//創(chuàng)建 DispatchGroup
let group =  DispatchGroup()
     //添加隊列
        group.enter()
        let queue = DispatchQueue.global()
        queue.async {
            for _ in 0...100{
                print("全局隊列")
            }
          //出隊列
        group.leave()
        }
        //如果需要上個隊列完成后再執(zhí)行可以用wait
        //group.wait()
        group.enter()
        let queue2 = DispatchQueue(label: "com.pingan.test", attributes: .concurrent)
        queue2.sync {
            
            for i in 0...10{
                print("",i)
            }
            group.leave()
        }
        //全部執(zhí)行完畢后通知
        group.notify(queue: DispatchQueue.main) {
            print("隊列執(zhí)行完畢")
        }


錯誤分析

1、主線程調(diào)用 DispatchQueue.main.sync 同步隊列,出現(xiàn)線程阻塞。

viewDidAppear方法的代碼相當于mainQueue的一個任務(假設任務A), 現(xiàn)在它里面加了個sync的{假設任務B}, 意味著任務B只有等任務A完成才能開始, 但是要完成任務A的話就必須先完成任務B,這樣相互等待出現(xiàn)線程阻塞。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容