在iOS中每一個進程啓動後都會創建一個主線程(UI線程),這個線程是其餘線程的父線程。因爲在iOS中除了主線程,其餘子線程是獨立於Cocoa Touch的,因此只有主線程能夠更新UI界面(新版iOS中,使用其餘線程更新UI可能也能成功,可是不推薦)。iOS中多線程使用並不複雜,關鍵是如何控制好各個線程的執行順序、處理好資源競爭問題。 安全
多線程開發中,須要明白一點,cpu在同一時間內,只能處理一件事情,多線程開發,只是cpu在各個線程之間來回穿梭調度,並非cpu可以同時執行多個任務,這一須要明確,本篇博客主要講一下NSThread服務器
一 NSThread的建立有三種方式多線程
//第一種 先建立 再啓動 注意 object參數 若是down方法須要參數 就在object這裏把參數傳遞給down方法spa
NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(down) object:nil];線程
[thread start];orm
//第二種 建立 不用啓動對象
[self performSelectorInBackground:@selector(down) withObject:nil];進程
//第三種 建立 不用啓動圖片
[NSThread detachNewThreadSelector:@selector(down) toTarget:self withObject:nil];資源
把比較耗時的操做放在down方法中,可是不要把UI的更新放在down方法中。
取消線程 [thread cancel];線程執行完操做後 會自動銷燬,也就是說 一個線程只能處理一個任務
二 線程之間的通訊 ,好比在子線程中下載一張圖片,下載完要回到主線程刷新UI;
[self performSelectorOnMainThread:@selector(update:) withObject:img waitUntilDone:YES];
這句代碼中的withObject:後面的參數img就是下載的圖片,而後在update:方法中 給imgView賦值,
這句代碼還有一種表達方式
[self performSelector:@selector(update:) onThread:[NSThread mainThread] withObject:img waitUntilDone:YES];
其實這裏還有一種比較簡單的方法 不用寫update方法了 既然給imgView賦值 直接這樣寫
[self.myImgView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:img waitUntilDone:YES];
三 線程間的安全問題
若是咱們的多個線程對同一個資源同時訪問,可能就會產生問題,好比咱們的賣票問題,好比開了三個線程賣票,共有10張票,線程一訪問時是10張,當線程一訪問完後,線程二又立刻來訪問,線程二訪問時仍是10張,線程二訪問完後,線程一賣了一張票,此時線程一返回給服務器的值是10-1 = 9張票,此時線程二也賣了一張,線程二返回的確定也是10-1=9張,這樣確定是有問題的,爲了不這種狀況,此時咱們要爲共同訪問的資源加鎖,仍是直接上代碼。
self.thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread1.name = @"窗口1";
self.thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread2.name = @"窗口2";
self.thread3 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread3.name = @"窗口3";
[self.thread1 start];
[self.thread2 start];
[self.thread3 start];
@synchronized(self){
int count = self.leftTicketCount;
if (count > 0) {
self.leftTicketCount = count - 1;
NSLog(@"%@賣了1張票,還剩%d張票",[NSThread currentThread].name,self.leftTicketCount);
}else{
return;
}
}
其實@synchronized()就是加鎖,後面小括號裏面就是鎖對象, 鎖對象的能夠是任意的對象,能夠直接用self,注意 鎖要用一個 不能每次建立一個 那樣和沒加鎖是同樣的效果,
NSThread的大致用法就這些,如今已經不是太經常使用NSThread 了 主要是用GCD 和NSOperation 另外還有一種Pthread 幾乎不用,有興趣的能夠了解下,GCD和NSOperation會在後面的章節寫下,哪裏有不對的地方,歡迎你們評批指正。