iOS開發Swift篇(02) NSThread線程相關簡單說明


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 }
線程安全Code示例

三 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 }
線程間通信示例Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM