Swift的多線程技術其實和Objective-C沒有區別。Thread是三種正常程序員會使用的多線程中最輕量級的,每個Thread對象表明着一個線程,可是須要本身管理線程的生命週期和線程的同步。線程同步對數據的加鎖會有必定的開銷。html
哪三種正常程序員會使用的多線程方案,問這個的同窗,你,出去~ 前面寫了辣麼多,Operation、GCD、Thread,都忘啦?git
若是要是較真,還有一個多線程技術,叫作pthread。咱們會在最後最後稍微說一下它。可是它絕對不是正常程序員如今還需使用的多線程方案。說完這句話不知道會不會被噴死。程序員
如下全部的代碼都是使用陳舊的Swift 3.0編寫。github
對,你沒看錯。陳舊的Swift 3.0。 Swift 5.0 都開始了,聽到這個消息的時候,心裏是五味雜陳的,有點點爲Swift擔憂了。尼瑪這4.0 發佈沒多久,5.0就開始了。 因此坊間纔有笑話說,學習iOS開發須要熟練使用Swift1.0 , Swift2.0 ,Swif 2.2...四種語言之類的。面試
一種是帶Selector
,一種不帶。bash
Thread.detachNewThread {
print("A new thread,name:\(Thread.current)")
}
//帶一個Selector
Thread.detachNewThreadSelector(#selector(threadPrint), toTarget: self, with: nil)
複製代碼
經過這種方法建立的thread會自動運行。多線程
這裏但是使用兩種方法直接建立Thread,並運行。app
Thread(block: <#T##() -> Void#>)
Thread(target: <#T##Any#>, selector: <#T##Selector#>, object: <#T##Any?#>)
複製代碼
下面是個例子,這種方法建立的thread須要手動start
運行ide
let customThread = Thread(target: self, selector: #selector(threadPrint), object: nil)
customThread.start()
複製代碼
任何繼承自NSObject的均可以很容易的經過這種方式調用點成方法。post
來,咱們一塊兒來看一下源文件:
extension NSObject {
open func performSelector(onMainThread aSelector: Selector, with arg: Any?, waitUntilDone wait: Bool, modes array: [String]?)
open func performSelector(onMainThread aSelector: Selector, with arg: Any?, waitUntilDone wait: Bool)
@available(iOS 2.0, *)
open func perform(_ aSelector: Selector, on thr: Thread, with arg: Any?, waitUntilDone wait: Bool, modes array: [String]?)
@available(iOS 2.0, *)
open func perform(_ aSelector: Selector, on thr: Thread, with arg: Any?, waitUntilDone wait: Bool)
@available(iOS 2.0, *)
open func performSelector(inBackground aSelector: Selector, with arg: Any?)
}
複製代碼
Thread的基本使用至關簡單,和GCD基本上差很少。也有啓動、暫停、取消、阻塞、設置優先級等等。
方法 | 做用 |
---|---|
start | 啓動 |
cancel | 暫停 |
exit | 取消 |
sleep | 阻塞 |
名稱 | 用途 |
---|---|
name | 給線程命名,方便查找 |
stackSize | 棧區大小,看看線程在棧區佔了多大空間 |
isMainThread | 是不是主線程 |
qualityOfService | 服務質量,iOS8.0推出,爲了取代優先級。 |
說明:thread設置了start
後,其實並非立刻就開始運行了。實質上是放進了可調度線程池,等待被CPU調用。線程執行結束以前,狀態可能會在就緒狀態 和 運行狀態 之間來回的切換 就緒狀態 和 運行狀態 之間的狀態切換由CPU來完成,程序員沒法干涉。
阻塞:正在運行thread能夠經過sleep的方式來阻塞線程的執行。
退出:thread在執行完畢以後會自動退出。若是執行了exit
,線程會強制退出。有幾點須要注意一下:
取消:這個cancel
和GCD同樣的啦,並無真證的取消線程,只是打了一個標誌。取消須要本身的實現。也就是在大人物開始以前,先判斷一下這個標誌位的狀態。要是歷來都沒寫過這個標誌位的狀態判斷,那cancel了也是白瞎。
你們還記得GCD中的信號量(semaphore)嘛?不記得話看看嘍,傳輸門:Swift多線程:GCD進階,單例、信號量、任務組 。Thread裏面的NSCondition和這個有點像。
這個玩意一共就四個方法,咱們索性都來看看:
方法名稱 | 做用 |
---|---|
wait | 使線程處於等待狀態 |
wait(until limit: Date) -> Bool | 在給定的時間到達時仍未有信號量出現, 就自動繼續了 |
signal | 喚醒線程 |
broadcast | 喚醒全部等待線程 |
NSCondition實現了NSLocking協議,因此它自己也有lock和unlock方法。配合在一塊兒能夠解決線程同步的問題,只要在線程開始時加鎖,取得資源後釋放鎖便可。使用時把須要加鎖的代碼放到lock
和unlock
之間就能夠了。
主要不要把什麼亂七八糟的都往加鎖代碼裏面放,放在這個裏面的應該是搶佔資源的讀取和修改。否則一個線程執行的時候另外一個線程就一直在等待,那還要多線程幹哈玩意?!
咱們搞個例子來看看。
需求:
1,模擬下載五張圖片、五篇文章;
2,圖片下載了兩張以後,暫停下載,轉而開啓文章下載;
3,下載三篇文章以後,暫停下載,轉而繼續下載剩下的三張圖片。
4,圖片下載完成後,下載完成剩下的兩篇文章。
說了是模擬啊,因此下載過程就直接print了噢。
class ViewController: UIViewController {
var downImages: Thread?
var downArticles: Thread?
let imageCondition = NSCondition()
let articleCondition = NSCondition()
override func viewDidLoad() {
super.viewDidLoad()
downImages = Thread(target: self, selector: #selector(downloadImages), object: nil)
downArticles = Thread(target: self, selector: #selector(downloadArticles), object: nil)
downImages?.start()
}
@objc private func threadPrint() {
Thread.sleep(forTimeInterval: 2)
print("After 2 seconds, I have been performed. I am \(Thread.current)")
}
@objc fileprivate func downloadImages() {
for index in 1...5 {
print("Downloading No.\(index) image.")
Thread.sleep(forTimeInterval: 1)
if index == 2 {
//start downArticles.開啓下載文章的線程
downArticles?.start()
//Lock the image thread.加鎖,讓下載圖片的線程進入等待狀態
imageCondition.lock()
imageCondition.wait()
imageCondition.unlock()
}
}
print("All images have been completed.")
//Signaling the article when all images completed.
// 等圖片都下載完成以後,激活下載文章的進程
articleCondition.signal()
}
@objc fileprivate func downloadArticles() {
for index in 1...5 {
print("The No.\(index) article will be downloading.")
Thread.sleep(forTimeInterval: 1)
if index == 3 {
//Signaling the image thread, let it continue to down.
//激活圖片的線程,讓它繼續下載圖片
imageCondition.signal()
//Lock the article thread.加鎖,讓下載文章的線程進入等待狀態
articleCondition.lock()
articleCondition.wait()
articleCondition.unlock()
}
}
print("There are 5 articles.")
}
}
複製代碼
咱們打印一下最終的打印結果:
好了。最後再說一下基本上沒人用的pthread
。
其實不知道這個多線程的技術如今還有誰會在用,除了面試可能會偶爾問一下這個名詞。 pthread是POSIX thread的簡寫。表示跨平臺的線程接口。
爲了可以寫Demo,非典型技術宅在浩瀚的Google海洋中游蕩了好久,而後,而後,而後放棄了...
怎麼能這麼不堅持吶,在OC時代曾經仍是能寫出來建立的。因而去看蘋果手冊,而後,而後,而後放棄了...
Threading Programming Guide 。這裏卻是提到了POSIX thread ,還讓人家去看pthread man page
。可是,明顯連接被刪除了。
蘋果爸爸。。。好想錘你小胸口。好吧,放棄了。
最後,全部的代碼都放在這裏了:gitHub 下載後給顆Star吧~ 麼麼噠~(~o ̄3 ̄)~ 愛大家~