iOS 面試常問之多線程

來源:互聯網
上載者:User

標籤:

 

本片圍繞多線程全面展開敘述。

1、為什麼要有多線程/多線程是用來幹什麼的?

2、多線程是什嗎?

3、如何建立多線程?

4、多線程在哪些情況下會使用/多線程使用情境?

5、三種多線程的優缺點?

 

1、為什麼要有多線程/多線程是用來幹什麼的?

  每個iOS應用程式都有個專門用來更新顯示UI介面、處理使用者的觸摸事件的主線程,因此不能將其他太耗時的操作放在主線程中執行,不然會造成主線程堵塞(出現卡機現象),帶來極壞的使用者體驗。一般的解決方案就是將那些耗時的操作放到另外一個線程中去執行,多線程編程是防止主線程堵塞,增加運行效率的最佳方法。

 

2、多線程是什嗎?

  多線程是個複雜的概念,按字面意思是同步完成多項任務,提高了資源的使用效率。

  從硬體、作業系統、應用軟體不同的角度去看,多線程被賦予不同的內涵,對於硬體,現在市面上多數的CPU都是多核的,多核的CPU運算多線程更為出色;

  從作業系統角度,是多任務,現在用的主流作業系統都是多任務的,可以一邊聽歌、一邊寫部落格;

  對於應用來說,多線程可以讓應用有更快的回應,可以在網路下載時,同時響應使用者的觸摸操作。

  在iOS應用中,對多線程最初的理解,就是並發,它的含義是原來先做燒水,再摘菜,再炒菜的工作,會變成燒水的同時去摘菜,最後去炒菜。

 

3、如何建立多線程?

  線程建立有三種方法:使用NSThread建立、使用GCD的dispatch、使用子類化的NSOperation,然後將其加入NSOperationQueue中。下面對這三種方法做詳細說明:

1, 使用NSThread建立

  1.1 NSThread 有兩種直接建立方式:

- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument

  說明:第一個是執行個體方法,第二個是類方法。

  selector :線程執行的方法,這個selector只能有一個參數,而且不能有傳回值

  target  :selector訊息發送的對象

  argument:傳輸給target的唯一參數,也可以是nil

 

  第一種方式會直接建立線程並且開始運行線程,第二種方式是先建立線程對象,然後再運行線程操作,在運行線程操作前可以設定線程的優先順序等線程資訊。

   PS:不顯式建立線程的方法:

//用NSObject的類方法  performSelectorInBackground:withObject: 建立一個線程:[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];

 

2, 使用子類化的NSOperation

  使用 NSOperation的方式有兩種:

  一種是用定義好的兩個子類:NSInvocationOperation 和 NSBlockOperation。

#import "ViewController.h"  #define kURL @"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"    @interface ViewController ()    @end    @implementation ViewController    - (void)viewDidLoad  {      [super viewDidLoad];      NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self                                                                             selector:@selector(downloadImage:)                                                                               object:kURL];            NSOperationQueue *queue = [[NSOperationQueue alloc]init];      [queue addOperation:operation];      // Do any additional setup after loading the view, typically from a nib.  }    -(void)downloadImage:(NSString *)url{      NSLog(@"url:%@", url);      NSURL *nsUrl = [NSURL URLWithString:url];      NSData *data = [[NSData alloc]initWithContentsOfURL:nsUrl];      UIImage * image = [[UIImage alloc]initWithData:data];      [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];  }  -(void)updateUI:(UIImage*) image{      self.imageView.image = image;  }  
  1. viewDidLoad方法裡可以看到我們用NSInvocationOperation建了一個後台線程,並且放到NSOperationQueue中。後台線程執行downloadImage方法。
  2. downloadImage 方法處理下載圖片的邏輯。下載完成後用performSelectorOnMainThread執行主線程updateUI方法。
  3. updateUI 並把下載的圖片顯示到圖片控制項中。

  另一種是繼承NSOperation。

 

如何控制線程池中的線程數?

  隊列裡可以加入很多個NSOperation, 可以把NSOperationQueue看作一個線程池,可往線程池中添加操作(NSOperation)到隊列中。線程池中的線程可看作消費者,從隊列中取走操作,並執行它。

//通過下面的代碼設定:[queue setMaxConcurrentOperationCount:5];//線程池中的線程數,也就是並行作業數。預設情況下是-1,-1表示沒有限制,這樣會同時運行隊列中的全部的操作。

 

3, 使用GCD的dispatch

  利用dispatch_queue_create函數建立串列Dispatch Queue (serial dispatch queue)

  使用dispatch_get_global_queue函數擷取全域並發Dispatch Queue (concurrent dispatch queue)

  使用dispatch_get_main_queue函數獲得應用主線程關聯的串列dispatch queue

  使用dispatch_get_current_queue函數作為調試用途,或者測試當前queue的標識。在block對象中調用這個函數會返回block提交到的queue(這個時候queue應該正在執行中)。在block對象之外調用這個函數會返回應用的預設並發queue。

 

GCD常用方法:

1. dispatch_async

  為了避免介面在處理耗時的操作時卡死,比如讀取網路資料,IO,資料庫讀寫等,我們會在另外一個線程中處理這些操作,然後通知主線程更新介面。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{      // 耗時的操作      dispatch_async(dispatch_get_main_queue(), ^{          // 更新介面      });  });  

2. dispatch_group_async

  dispatch_group_async可以實現監聽一組任務是否完成,完成後得到通知執行其他的操作。這個方法很有用,比如你執行三個下載任務,當三個任務都下載完成後你才通知介面說完成的了。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  dispatch_group_t group = dispatch_group_create();  dispatch_group_async(group, queue, ^{      [NSThread sleepForTimeInterval:1];      NSLog(@"group1");  });  dispatch_group_async(group, queue, ^{      [NSThread sleepForTimeInterval:2];      NSLog(@"group2");  });  dispatch_group_async(group, queue, ^{      [NSThread sleepForTimeInterval:3];      NSLog(@"group3");  });  dispatch_group_notify(group, dispatch_get_main_queue(), ^{      NSLog(@"updateUi");  });  dispatch_release(group);  

dispatch_group_async是非同步方法,運行後可以看到列印結果:

2012-09-25 16:04:16.737 gcdTest[43328:11303] group12012-09-25 16:04:17.738 gcdTest[43328:12a1b] group22012-09-25 16:04:18.738 gcdTest[43328:13003] group32012-09-25 16:04:18.739 gcdTest[43328:f803] updateUi

每個一秒列印一個,當第三個任務執行後,upadteUi被列印。

 

3. dispatch_barrier_async

  dispatch_barrier_async是在前面的任務執行結束後它才執行,而且它後面的任務等它執行完成之後才會執行

dispatch_queue_t queue = dispatch_queue_create("gcdtest.rongfzh.yc", DISPATCH_QUEUE_CONCURRENT);  dispatch_async(queue, ^{      [NSThread sleepForTimeInterval:2];      NSLog(@"dispatch_async1");  });  dispatch_async(queue, ^{      [NSThread sleepForTimeInterval:4];      NSLog(@"dispatch_async2");  });  dispatch_barrier_async(queue, ^{      NSLog(@"dispatch_barrier_async");      [NSThread sleepForTimeInterval:4];    });  dispatch_async(queue, ^{      [NSThread sleepForTimeInterval:1];      NSLog(@"dispatch_async3");  });  

  列印結果:

2012-09-25 16:20:33.967 gcdTest[45547:11203] dispatch_async12012-09-25 16:20:35.967 gcdTest[45547:11303] dispatch_async22012-09-25 16:20:35.967 gcdTest[45547:11303] dispatch_barrier_async2012-09-25 16:20:40.970 gcdTest[45547:11303] dispatch_async3

請注意執行的時間,可以看到執行的順序如上所述。

 

4. dispatch_apply 

  執行某個程式碼片段N次。

dispatch_apply(5, globalQ, ^(size_t index) {    // 執行5次});

 

4、多線程在哪些情況下會使用/多線程使用情境?

  在網路請求,讀取大量檔案,操作資料庫,大量資料解析,單例,延遲等一些耗時操作中,都會用到多線程。

 

5、三種多線程的優缺點?

  1. NSThread優點是比其他兩種多線程方案較輕量級,更直觀地控制線程對象。缺點是需要自己管理線程的生命週期,線程同步。線程同步對資料的加鎖會有一定的系統開銷。

  2. 項目中使用NSOperation的優點是NSOperation是對線程的高度抽象,在項目中使用它,會使項目的程式結構更好,子類化NSOperation的設計思路,是具有物件導向的優點(複用、封裝),使得實現是多線程支援,而介面簡單,建議在複雜項目中使用。  3. 項目中使用GCD的優點是GCD本身非常簡單、易用,對於不複雜的多線程操作,會節省代碼量,而Block參數的使用,會是代碼更為易讀,建議在簡單項目中使用。

 

iOS 面試常問之多線程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.