多線程---iOS-Apple蘋果官方文檔翻譯

本系列全部開發文檔翻譯連接地址:iOS7開發-Apple蘋果iPhone開發Xcode官方文檔翻譯PDF下載地址(2013年12月29日更新版)html

 

page1image576.png
多線程 

技術博客http://www.cnblogs.com/ChenYilong/ 新浪微博http://weibo.com/luohanchenyilong
page1image2200.png page1image2360.png
多線程的應用 
 耗時操做,例如網絡圖片視頻歌曲書籍等資源下載  遊戲中的聲音播放
page2image1480.png 
page2image1640.png
 
page3image432.png
 
page3image592.png
多線程示意圖 
 充分發揮多核處理器的優點,併發(同時執行) 執行任務讓系統運行的更快、更流暢
page4image1440.png
 
page4image1600.png
進程與線程概念 
  一個運行的程序就是一個進程或者叫作一個任務 
  一個進程至少包含一個線程,線程是程序的執行流 
  iOS程序啓動時,在建立一個進程的同時, 會開始運行一個線程,該 線程被稱爲主線程 
  主線程是其餘線程最終的父線程,全部界面的顯示操做必須在主線程 進行    
  後臺線程沒法更新UI界面和響應用戶點擊事件 
  系統中的每個進程都有本身獨立的虛擬內存空間,而同一個進程中 
的多個線程則共用進程的內存空間 
  每建立一個新的線程,都會消耗必定內存和CPU時間 
  當多個線程對同一個資源出現爭奪的時候須要注意線程安全問題 
page5image3944.png
多線程的優點與難點 
 優點
  充分發揮多核處理器優點,將不一樣線程任務分配給不一樣的處 
   理器,真正進入「並行運算」狀態

  耗時輪詢或者併發需求高等任務分配到其餘線程執行, 並由主線程負責統一更新界面會使得應用程序更加流暢,用 戶體驗更好 
  當硬件處理器的數量增長,程序會運行更快,而無需作任何 調整 
 難點 
  共享資源的「爭奪」 
  多線程是爲了同步完成多項任務,不是爲了提升運行效率, 而是爲了經過提升資源使用效率來提升系統的總體性能 
page6image3896.png
多線程使用注意事項 
 線程使用不是無節制的 iOS中的主線程的堆棧大小是1M
 從第二個線程開始都是512KB
 這些數值不能經過編譯器開關或線程API函數更改
 只有主線程有直接修改UI的能力
page7image2136.png
iOS的三種多線程技術 程序員

1.  NSThread  每一個 NSThread 對象對應一個線程,量級較輕(真正的多線
程)
2.  如下兩點是蘋果專門開發的「併發」技術,使得程序員能夠再也不去 關心線程的具體使用問題
.1.    NSOperation/NSOperationQueue  面向對象的線程技術 
.2.    GCD —— Grand Central Dispatch (派發)  是基於 C 語言的框架, 能夠充分利用多 
     核 ,是蘋果推薦使用的多線程技術
.
以上這三種編程方式從上到下,抽象度層次是從低到高的, 抽象度越高 的使用越簡單,也是 Apple 最推薦使用的 。可是就目前而言, iOS 的開發者, 須要瞭解三種多線程技術的基本使用過程。由於不少框架技術分別使用 了不一樣多線程技術。
page8image3688.png
三種多線程技術的對比 
  NSThread:
   優勢: NSThread  比其餘兩個輕量級, 使用簡單 
   缺點: 須要本身管理線程的生命週期、線程同步、加鎖、睡眠以 及喚醒等 。線程同步 對數據的加鎖 會有必定的系統開銷 
  NSOperation : 
   不須要關心線程管理,數據同步的事情,能夠把精力放在本身需 
要執行的操做上 
   NSOperation 是面向對象的    GCD : 
   Grand Central Dispatch 由蘋果開發的一個多核編程的解決方案   iOS4.0+ 才能使用,是替代 NSThread ,  NSOperation 的高效和強大 的技術 
//轉載請註明出處--本文永久連接:http://www.cnblogs.com/ChenYilong/p/3494799.html
   GCD 是基於 C 語言的 
page9image4392.png
演練( 1 ) NSObject 的多線程方法 —— 準備 
.1.    建立一個耗時較長的操做 
.2.    建立一個耗時較短的操做 
.3.    在界面中心放置兩個按鈕,分別調用 這兩個任務 
.4.    使用 [NSThread currentThread] 分別打 印各個任務所在的線程 
.5.    運行觀察效果 
   提示: 
   NSLog 是一個至關耗時的操做 在應用 程序正式發佈前,必定記住須要對應用 中的 NSLog 方法進行處理 
   不管使用哪種多線程技術,都可以使 用 [NSThread currentThread] 查看當前任 務所在線程 
page10image4312.png 
page10image4472.png
 
page11image432.png
 
page11image592.png
NSObject 的多線程方法 —— 後臺線程
- ( void )performSelectorInBackground:( SEL )aSelector
withObject:( id )arg 
   一般,因爲線程管理相對比較繁瑣,而不少耗時的任務又沒法知道其準 確的完成時間,所以可使用 performSelectorInBackground 方法 直接新建一個後臺線程,並將選擇器指定的任務在後臺線程執行,而無 需關心具體的 NSThread 對象   
   提示: 
  performSelectorInBackground 方法自己是在主線程中執行的, 
而選擇器指定的方法是在後臺線程中進行的 
  使用 performSelectorInBackground 方法調用的任務能夠更新 
UI 界面   在大型交互式遊戲中,一般使用此方法在後臺線程播放音效   
page12image3520.png
@autoreleasepool  
  內存管理對於多線程很是重要
  Objective-C 能夠憑藉 @autoreleasepool 使用內存資源,並須要時回 收資源
  每一個線程都須要有 @autoreleasepool ,不然可能會出現內存泄漏 
page13image1912.png
NSObject 的多線程方法 —— 主線程
- ( void )performSelectorOnMainThread:( SEL )aSelector
withObject:( id )arg waitUntilDone:( BOOL )wait; 
  若是要更新 UI 界面,能夠在後臺線程中調用
performSelectorOnMainThread 方法 
  提示 :儘管使用 performSelectorInBackground 方法調用的任務 能夠更新 UI 界面,可是在實際開發中,涉及到 UI 界面的更新操做,還 是要使用 performSelectorOnMainThread 方法,以免沒必要要的 麻煩
page14image2640.png
NSObject 的多線程小結 
  開啓後臺執行任務的方法
-  ( void )performSelectorInBackground:( SEL )aSelector withObject:( id )arg
  在後臺線程中通知主線程執行任務的方法   ( void )performSelectorOnMainThread:( SEL )aSelector
withObject:( id )arg waitUntilDone:( BOOL )wait;    獲取線程信息
[ NSThread  currentThread ];    線程休眠
   [ NSThread  sleepForTimeInterval : 1.0f ];
  特色:   使用簡單,量級輕   不能控制線程的執行順序 
page15image4016.png
NSThread    建立線程方法: 
1.  + ( void )detachNewThreadSelector:( SEL ) selector  toTarget:( id ) target  withObject:( id ) argument ; 
2.  - ( id )initWithTarget:( id ) target  selector: ( SEL ) selector  object:( id ) argument ; 
  參數說明:   selector : 線程執行的方法 ,只能有一個參數,不能有返回值 
  target : selector 消息發送的對象    argument :傳輸給 target 的惟一參數,也能夠是 nil
page16image3216.png
NSThread 演練 —— 加載圖片 
  detachNewThreadSelector
方法會直接啓動線程方法 
  initWithTarget 須要調用  start 方法纔可以啓動線程方 法 
 
page17image2280.png
 
page17image2440.png
NSOperation & NSOperationQueue
  NSOperation 的兩個子類 1.  NSInvocationOperation 2.  NSBlockOperation
  工做原理:
1.  NSOperation 封裝要執行的操做
2.  將建立好的 NSOperation 對象放 NSOperationQueue 中 
3.  啓動 OperationQueue 開始新的線程執行隊列中的操做
  注意事項:
.1.    使用多線程時一般須要控制線程的併發數 ,由於線程會消耗系統資源, 
    同時運行的線程過多,系統會變慢
.
.2.    使用如下方法能夠控制併發的線程數量: 
-  ( void )setMaxConcurrentOperationCount:( NSInteger )cnt; 
//轉載請註明出處--本文永久連接:http://www.cnblogs.com/ChenYilong/p/3494799.html
page18image4024.png
NSOperation 演練 —— 加載圖片 
.1.    不能直接使用 NSOperation 
.2.    定義完操做後, 將添加到操做隊列中 ,便可啓動異步操做,不然操 做任務仍然在主線程中執行 
.3.    使用 NSBlockOperation 更加簡單直接 
.4.    使用 setMaxConcurrentOperationCount 能夠限制併發操做數 
量,下降系統開銷   
.5.    使用 addDependency 能夠創建操做之間的依賴關係,設定操做的執行 順序 
page19image3016.png
  page20image432.png
 
page20image592.png
 
page21image432.png
 
page21image592.png
GCD    GCD 是基於 C 語言的框架
  工做原理 :
   讓程序平行排隊的特定任務,根據可用的處理資源, 安排它們在 
   任何可用的處理器上執行任務

   要執行的任務能夠是一個函數或者一個 block 
   底層是經過線程實現的,不過程序員能夠沒必要關注實現的細節 
   GCD 中的 FIFO 隊列稱爲 dispatch queue ,能夠保證先進來的任務先 獲得執行 
   dispatch_notify  能夠實現 監聽一組任務是否完成 ,完成後得 到通知 
  GCD 隊列 : 1.  全局隊列: 全部添加到主隊列中的任務都是併發執行的 2.  串行隊列: 全部添加到串行隊列中的任務都是順序執行的  3.  主隊列: 全部添加到主隊列中的任務都是在主線程中執行的 
page22image4424.png
獲取隊列的方法 
  全局隊列(可能會開啓多條線程)  dispatch_queue_t  queue =
dispatch_get_global_queue ( DISPATCH_QUEUE_PRIORITY_DEFAULT ,  0 );     串行隊列(只可能會開啓一條線程) 
dispatch_queue_t  queue =  dispatch_queue_create ( "myQueue" ,  DISPATCH_QUEUE_SERIAL ); 
  主隊列    dispatch_get_main_queue (); 
page23image2952.png
GCD 任務的執行方式 —— 同步 & 異步 
  異步操做 
  dispatch_async  在其餘線程執行任務,會開啓新的線程      異步方法沒法肯定任務的執行順序 
  同步操做   dispatch_sync  在當前在當前線程執行任務,不開啓新的線程 
  同步操做與隊列無關 
  同步方法會依次執行,可以決定任務的執行順序      更新界面 UI 時,最好使用同步方法 
page24image2880.png
GCD 演練 —— 加載圖片 
  GCD 的優勢:   充分利用多核   全部的多線程代碼集中在一塊兒,便於維護    GCD 中無需使用 @autoreleasepool
  若是要順序執行,可使用 dispatch_sync 同步方法      dispatch_async 沒法肯定任務的執行順序 
page25image2320.png
單例模型 
  目的 :   保證在內存中永遠只有類的單個實例
  創建方法 :
1.  聲明一個靜態成員變量,記錄惟一實例 
2.  重寫 allocWithZone 方法
allocWithZone 方法是對象分配內存空間時,最終會調用的方法, 重寫該方法,保證只會分配一個內存空間
3.  創建 sharedXXX 類方法,便於其餘類訪問
//轉載請註明出處--本文永久連接:http://www.cnblogs.com/ChenYilong/p/3494799.html



互斥鎖的目的,一次只讓一個線程訪問資源,從而達到資源的線程安全。編程

 

iPhone 開發中,一般要儘可能避免使用互斥鎖! 
page26image2832.png

多線程演練 —— 賣票 
  系統預設   共有 30 張票能夠銷售( 開發時能夠少一些,專一實現)    售票工做由兩個線程併發進行   沒有可出售票據時,線程工做中止   兩個線程的執行時間不一樣,模擬售票人員效率不一樣   使用一個多行文本框公告售票進度(主線程更新 UI )
  線程工做安排   主線程:負責更新 UI
  線程 1 :模擬第 1 名賣票員    線程 2 :模擬第 2 名賣票員    兩個線程 幾乎 同時開始賣票
page27image3240.png
page28image552.png
單線程賣票流程圖 
page28image1168.png
page29image552.png
多線程賣票示意圖 
page29image1168.png
演練準備 —— 更新 UI 方法,由主線程調用 
// 1.  取出當前的文本 
NSMutableString  *str = [ NSMutableString  stringWithString : [ self . textView  text ]]; 
// 2.  追加文本  [str  appendFormat : @"%@\n" , text];
// 3.  設置文本  [ self . textView  setText :str];
// 4.  選中最末位置,實現自動滾動效果  NSRange  range =  NSMakeRange (str. length  -  1 ,  1 );  [ self . textView  scrollRangeToVisible :range]; 
//轉載請註明出處--本文永久連接:http://www.cnblogs.com/ChenYilong/p/3494799.html
page30image3576.png
賣票演練 
  資源爭奪
   僅使用單例模式沒法解決資源爭奪問題 
   使用互斥鎖 @synchronized 能夠保證多個線程不會使用同一代碼塊,並且比  NSLock 具備更好的性能   
   爲了保證屬性安全,被爭奪資源的屬性應該設置爲原子屬性 atomic    GCD 
   GCD 的多線程更加靈活、方便 
   dispatch_group_notify 能夠監聽一組任務是否完成 。這個方法頗有用,好比 
    你執行三個下載任務,當三個任務都下載完成後,才通知界面說已經完成

   若是不須要監聽一組任務,能夠直接使用 dispatch_async 方法 
  NSOperation
  更新界面時使用 [[ NSOperationQueue 
mainQueue ] addOperationWithBlock : 方法      NSThread 
  涉及到線程調度問題,平常開發不建議使用 
page31image4864.png
page32image552.png
三種多線程技術的流程對比 
page32image1168.png
關於 iOS 多線程使用的建議 
  掌握大綱內容便可,關於多個線程之間的調度問題,待往後熟練後可
以自行學習,目前不建議再繼續深刻   
  關於多線程必須記住的三個要點
  只能在主線程中更新 UI
  共享數據爭奪的處理 ,互斥鎖 @synchronized ( self ) 和原子屬
atomic
  不要使用多種多線程技術去爭奪同一個資源 
  使用多線程是爲了處理併發操做的。若是有可能,咱們不要去作搶資 源的事情 互斥鎖的代價至關的昂貴 
page33image2976.png

 

//轉載請註明出處--本文永久連接:http://www.cnblogs.com/ChenYilong/p/3494799.html 安全

https://www.evernote.com/shard/s227/sh/8e2008b3-1d9e-42e6-b193-551e6dbe7440/e39f99e835da159ac641e28679c3c00b網絡

相關文章
相關標籤/搜索