iOS開發Swift篇(02) NSThread線程相關簡單說明
一 說明
1)關於多線程部分的理論知識和OC實現,在之前的博文中已經寫明,所以這里不再說明。
2)該文僅僅簡單講解NSThread在swift語境中的一些使用和注意點,別他。
3)本文涉及代碼可以從https://github.com/HanGangAndHanMeimei/Code地址獲得。
二 NSThread的基本使用和創建
1)基本用法(主線程|當前線程)
1 //1.獲得執行該方法的當前線程 2 let currentThread = NSThread.currentThread() 3 print("當前線程為\(currentThread)") 4 5 //2.獲得應用程序的主線程 6 let mainThread = NSThread.mainThread() 7 print("應用程序的主線程\(mainThread)") 8 9 //3.判斷當前線程是否是主線程 10 let isMain = NSThread.isMainThread()
2)創建線程
說明:此處列出創建線程的四種方法:分別是
直接創建|分離出一條子線程|創建一條后台線程|自定義線程類繼承自NSThread重寫內部的main方法封裝任務,然后init創建。
1 //NSThread創建線程的四種方式 2 func createNewThreadWithNSThreadMethodOne() 3 { 4 //1.創建線程 5 let thread = NSThread.init(target: self, selector:Selector("run"), object: nil) 6 7 //設置線程的名稱 8 thread.name = "線程A" 9 10 //2.啟動線程 11 thread.start() 12 } 13 14 func createNewThreadWithNSThreadMethodTwo() 15 { 16 //分離出一條子線程,自動啟動線程,但無法獲得線程對象 17 NSThread.detachNewThreadSelector(Selector("run"), toTarget: self, withObject: nil) 18 } 19 20 func createNewThreadWithNSThreadMethodThree() 21 { 22 //開啟一條后台線程,自動啟動線程,但無法獲得線程對象 23 self.performSelectorInBackground(Selector("run"), withObject: nil); 24 } 25 26 func createNewThreadWithNSThreadMethodFour() 27 { 28 //let thread = CustomThread.init(target: self, selector:Selector("run"), object: nil) 29 let thread = CustomThread(); 30 thread.start() 31 } 32 33 func run() 34 { 35 //獲得當前執行run方法的線程 36 let thread = NSThread.currentThread() 37 print("run--\(thread.name)-\(thread)"); 38 }
三 NSThread線程的狀態和線程安全
1)線程的狀態
線程的狀態:新建-就緒-運行-阻塞-死亡
1 //線程的退出 2 NSThread.exit() 3 //線程的休眠1 4 NSThread.sleepForTimeInterval(2.0) 5 //線程的休眠2 6 NSThread.sleepUntilDate(NSDate.init(timeIntervalSinceNow: 3.0))
2)線程安全
說明:多線程訪問同一個資源的時候可能會出現數據錯亂等安全問題,解決方法是對必要的代碼段進行加鎖。
注意:在OC中加互斥鎖使用@synchronized(self) {},在swift可以使用objc_sync_enter(self)和objc_sync_exit(self)方法,注意這兩個方法必須成對使用,把要加鎖的代碼放在中間

1 class ViewController: UIViewController { 2 3 //設置總票數為100張 4 var totalTickets = 100 5 6 override func viewDidLoad() { 7 super.viewDidLoad() 8 9 //多線程訪問資源加鎖 10 //創建三條線程分別代表售票員A、售票員B、售票員C 11 let thread01 = NSThread.init(target: self, selector:Selector("saleTickect"), object: nil) 12 let thread02 = NSThread.init(target: self, selector: Selector("saleTickect"), object: nil); 13 let thread03 = NSThread.init(target: self, selector: Selector("saleTickect"), object: nil); 14 15 //設置線程的名稱 16 thread01.name = "售票員A" 17 thread02.name = "售票員B" 18 thread03.name = "售票員C" 19 20 //開啟線程 21 thread01.start() 22 thread02.start() 23 thread03.start() 24 25 } 26 27 //模擬售票的函數 28 func saleTickect() 29 { 30 while(true) 31 { 32 //加互斥鎖 33 /* 34 * 1)同OC中的@synchronized(self) {} 35 * 2)objc_sync_enter(self)和objc_sync_exit(self)必須成對使用,把要加鎖的代碼放在中間 36 */ 37 38 objc_sync_enter(self) 39 40 //檢查是否有余票,如果有則賣出去一張 41 let temp = totalTickets 42 for var i=0;i<100000;i++ 43 { 44 //空的for循環,模擬延遲 45 } 46 47 if(temp>0) 48 { 49 totalTickets = temp - 1 50 print("\(NSThread.currentThread().name)賣出去了一張票,還剩\(totalTickets)") 51 }else 52 { 53 print("\(NSThread.currentThread().name)發現票已經賣完了") 54 break; 55 } 56 57 objc_sync_exit(self) 58 } 59 60 } 61 62 }
三 NSThread線程間通信
1)說明
所謂線程間通信,即如何從一個線程進入到另一個線程繼續執行任務或者是傳遞參數(如從子線程回到主線程)
下面的代碼示例演示在主線程中先創建一個子線程下載圖片,當圖片下載完成后又切換到主線程設置圖片的操作。

1 //!!!注意,該案例內部下載圖片,發送了http請求需要修改info.plist文件 2 class ViewController: UIViewController { 3 4 @IBOutlet weak var imageView: UIImageView! 5 6 override func viewDidLoad() { 7 super.viewDidLoad() 8 9 //程序啟動后開子線程下載圖片,圖片下載完成之后回到主線程設置圖片 10 NSThread.detachNewThreadSelector(Selector("downloadImage"), toTarget: self, withObject: nil) 11 } 12 13 func downloadImage() 14 { 15 //1.獲得要下載圖片的url 16 let url = NSURL.init(string: "http://p9.qhimg.com/t014d1bd470cb60ac6e.jpg") 17 18 //2.把url地址指向資源的二進制下載到本地 19 let imageData = NSData.init(contentsOfURL: url!) 20 21 //3.把二進制數據轉換為圖片 22 let image = UIImage.init(data: imageData!); 23 24 //4.打印查看當前線程(應該是在子線程中下載圖片) 25 print("當前線程為\(NSThread.currentThread())") 26 27 //5.線程間通信 28 //方法一 29 self.performSelectorOnMainThread(Selector("showImage:"), withObject: image, waitUntilDone:true) 30 //方法二 31 //imageView.performSelectorOnMainThread(Selector("setImage:"), withObject: image, waitUntilDone:true) 32 } 33 34 35 func showImage(image:UIImage) 36 { 37 //設置圖片 38 imageView.image = image 39 40 //打印查看設置圖片操作的線程 41 print("處理UI刷新操作的線程\(NSThread.currentThread())") 42 43 } 44 }