iOS並發編程(一)——thread

來源:互聯網
上載者:User
      當目前為止,你的iOS代碼是不是都只有一個mainThread,你的程式一直都是串列的,總是幹完任務A再去幹任務B,哪怕AB之間完全沒有依賴關係。mainThread是用來處理與UI相關的事件的,如果你在mainThread中執行一些需要耗費大量時間的任務(比如從網路下載資料),那麼這個程式的使用者體驗將是極差的,因為使用者往往需要等待很久。 重要:任何與UI相關的操作都應該放在mainThread中來處理。      同時,要知道現在是個行動裝置都在標稱自己是多核的,你好意思讓你的程式只佔用其中一個,而讓另外的都自顧自兒的空轉嗎?!我想我沒有必要去闡述多線程編程有什麼哪些優點,會帶來什麼好處,因為大家都懂的。      當然,要實現程式的並發,也並不要求運行它的裝置一定是多核的,我們可以通過對CPU的調度(時間片輪轉)來實現”表明上“的同時執行。在開始這篇文章之前,有必要先解釋一下幾個關鍵性的術語:      thread(線程)——可簡單理解為可獨立執行的程式碼片段。      process(進程)——指一個正在啟動並執行可執行程式,一個進程可以包含多個線程。      task(任務)——對程式執行的工作的抽象。      concurrency(並發)——指程式可以同時或者幾乎同時執行多個任務。
      前面提到,即使是在單核CPU的情況下,也可以實現程式的並發。比如,在1s之內有10個相同優先順序的task需要執行,系統可以將1s的CPU時間均分為10個100ms,並把這10個100ms的CPU時間分配給10個task。那麼,表面上看來,在1s的CPU時間內這10個task同時執行了。但是,現在的系統已經實現了真正的多核,沒有必要這麼吝嗇的在一個CPU上去瓜分時間片,況且CPU的調度也是耗費資源和時間的。1.1 利用線程實現並發      在iOS下實現程式的並發,將是前所未有的簡單。最直接的:
[self performSelectorInBackground:@selector(try:) withObject:para1];
       簡單的調用一下performSelectorInBackground:withObject:函數,把你想要並發執行的函數(任務)傳給第一個參數,如樣本中的try,第二個參數para1是try函數的參數。這樣系統就自動為你開闢了一個後台線程,你的任務已經是在後台而不是mainThread了。     當然你也可以自己手動建立一個新的Thread,如下:
[NSThread detachNewThreadSelector:@selector(try:)  toTarget:self withObject:para1]
     這是類方法。也可以建立一個Thread執行個體:
NSThread* myThread = [[NSThread alloc] initWithTarget:self selector:@selector(myThreadMainMethod:)  object:nil];//start thread manually[myThread start];

   為了防止記憶體泄露,如果你使用的是記憶體管理模型(即含有retain、release操作)你應該在try中添加autoreleasepool,像main函數中做的那樣:

-(void)try:(id)para1{    @autoreleasepool{                /*do something here*/    }}

     你調用後台線程時,也應該這麼做,這兩種方式並沒有實質性的區別。如果你使用的是記憶體回收機制(ARC),那麼建立的自動釋放池會被忽略,但它是無害的。

    如果你建立了多個Thread執行個體,你可以通過:

performSelector:onThread:withObject:waitUntilDone:

方法來調用它們執行相應的task。     你還可以對建立的Thread執行個體進行相應的配置。1.1.1 堆棧     你在程式中建立的每一個線程,系統都會在進程空間中分配一部分記憶體空間作為該線程的堆棧,該堆棧管理線程的資料,比如線程中所有的局部變數都將在堆棧裡。你可以調用下列函數來配置和訪問線程堆棧:
- (NSUInteger)stackSize NS_AVAILABLE(10_5, 2_0);- (void)setStackSize:(NSUInteger)s NS_AVAILABLE(10_5, 2_0);+ (NSArray *)callStackReturnAddresses NS_AVAILABLE(10_5, 2_0);+ (NSArray *)callStackSymbols NS_AVAILABLE(10_6, 4_0);
1.1.2 線程的鍵-值字典     每個線程都維護了一個鍵-值字典,該字典中儲存了該線程的一些狀態資訊,字典線上程啟動並執行過程中隨時都可以訪問。你可以使用NSThread的threadDictionary方法來擷取一個NSMutableDictionary對象,並在裡面添加線程需要的索引值對。
- (NSMutableDictionary *)threadDictionary;
1.1.3  線程的運行狀態

        配置線程何時運行,何時退出,以及得知線程當前的運行狀態。      讓線程先睡眠一段時間,然後自動運行:

+ (void)sleepUntilDate:(NSDate *)date;+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
      取消線程執行,開始線程,退出線程:
- (void)cancel NS_AVAILABLE(10_5, 2_0);- (void)start NS_AVAILABLE(10_5, 2_0);+ (void)exit;

      查詢線程的狀態:

- (BOOL)isExecuting NS_AVAILABLE(10_5, 2_0);- (BOOL)isFinished NS_AVAILABLE(10_5, 2_0);- (BOOL)isCancelled NS_AVAILABLE(10_5, 2_0);

1.1.4  優先順序

     在預設的情況下,建立的新線程的優先順序與當前線程是相同的。核心調度演算法在決定該運行那個線程時,會把線程的優先順序作為考量因素,較高優先順序的線程會比較低優先順序的線程具有更多的運行機會。你可以通過:

//class method+ (double)threadPriority;+ (BOOL)setThreadPriority:(double)p;//instance method- (double)threadPriority NS_AVAILABLE(10_6, 4_0);- (void)setThreadPriority:(double)p NS_AVAILABLE(10_6, 4_0);

來設定線程的優先順序。

重要:讓你的線程處於預設優先順序值是一個不錯的選擇。增加某些線程的優先順序,同時有可能增加了某些較低優先順序線程的饑餓程度。如果你的應用程式套件組合含較高優先順序和較低優先順序線程,而且它們之間必須互動,那麼較低優先順序的饑餓狀態有可能阻塞其他線程,並造成效能瓶頸。


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.