iOS 多線程

一 多線程基礎面試

 1.進程:進程就是系統中正在運行的應用程序.每一個進程是相互獨立的且都運行在各自受保護的運行空間內.  編程

  好比同時打開迅雷、Xcode,系統就會分別啓動2個進程.緩存

  2.線程:進程在執行任務是必須開闢線程,進程中的全部任務都在線程中進行.一個進程能夠開闢一條線程,也能夠開闢多條線程.安全

  好比酷狗音樂這個進程在執行播放音樂這個線程的同時,還在執行下載音樂這條線線程.多線程

二 線程的串行併發

  在同一時間一個線程只能執行一個任務,若是一個線程有多條任務要執行就得按前後順序執行,一個線程不能同時進行多個任務.app

三 多線程框架

  一個進程能夠開闢多條線程,每條線程能夠執行不一樣的任務,看上去是每條相稱在同時進行,實際上是CPU在不一樣線程間快速的切換.異步

  CPU在同一時間只能執行一條線程.async

  多線程技術能夠提升執行程序的效率,提升資源利用率.

  可是在建立線程耗內存耗時間,且若是線程開闢太多也會下降程序的性能,並且多線程的程序設計難度也更大.

四 多線程在IOS開發中的應用

  一個iOS程序運行後,會自動開闢主線程(又叫UI線程).

  主線程主要用來顯示和刷新UI界面以及處理UI事件.

  主線程使用過程當中的注意事項:主線程處理耗時操做時會有卡死的感受,影響UI的流暢度,所以不可將耗時較多的操做放在主線程中.

  主線程只用來顯示和刷新UI界面以及處理UI事件.

五 多線程的實現方案

  1.pthread 幾乎不用

  2.NSThread 幾乎不用

  3.GCD 常使用

    GCD基於C語言,自動管理現成的生命週期,可從分利用多喝處理器來處理線程. 

  4.NSOperation 常使用

    NSOperation基於GCD自動管理線程的生命週期.

六 NSThread(掌握)

  1.建立和啓動線程的3種方式

  

/**1  先建立,後啓動*/
  // 建立
  NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(download:) object:nil];
  // 啓動
  [thread start];

/**2  建立完自動啓動*/
  [NSThread detachNewThreadSelector:@selector(download:) toTarget:self withObject:nil];

/**3  隱式建立(自動啓動)*/
  [self performSelectorInBackground:@selector(download:) withObject:nil];

 

 

  2.常見方法

  1> 得到當前線程

+ (NSThread *)currentThread; 

  2> 得到主線程

+ (NSThread *)mainThread; 

  3> 睡眠(暫停)線程 

+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;

  4> 設置線程的名字

- (void)setName:(NSString *)n;
- (NSString *)name;

 

七 線程同步(掌握)

  1.實質:爲了防止多個線程搶奪同一個資源形成的數據安全問題

  2.實現:給代碼加一個互斥鎖(同步鎖)

@synchronized(self) {
    // 被鎖住的代碼
  }

八 GCD

  1.隊列和任務

  1> 任務 :須要執行什麼操做

  * 用block來封裝任務

   2> 隊列 :存聽任務

  * 全局的併發隊列 : 可讓任務併發執行

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

  * 本身建立的串行隊列 : 讓任務一個接着一個執行

dispatch_queue_t queue = dispatch_queue_create("cn.heima.queue", NULL); 

  * 主隊列 : 讓任務在主線程執行  

dispatch_queue_t queue = dispatch_get_main_queue();

 

  2.執行任務的函數

  1> 同步執行 : 不具有開啓新線程的能力

  dispatch_sync...

 

  2> 異步執行 : 具有開啓新線程的能力

  dispatch_async...

 

  3.常見的組合(掌握)

  1> dispatch_async + 全局併發隊列

  2> dispatch_async + 本身建立的串行隊列

 

  4.線程間的通訊(掌握)

dispatch_async(dispatch_get_main_queue(), ^{

       // 回到主線程,執行UI刷新操做
     });
});

 

 

  5.GCD的全部API都在libdispatch.dylib,Xcode會自動導入這個庫

  * 主頭文件 : #import <dispatch/dispatch.h>

 

  6.延遲執行(掌握)

  1> perform....

// 3秒後自動回到當前線程調用self的download:方法,而且傳遞參數:@"http://555.jpg"
[self performSelector:@selector(download:) withObject:@"http://555.jpg" afterDelay:3];

  2> dispatch_after...

// 任務放到哪一個隊列中執行

  dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

  double delay = 3; // 延遲多少秒

  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), queue, ^{

      // 3秒後須要執行的任務  

  });

 

  7.一次性代碼(掌握) 

static dispatch_once_t onceToken;

  dispatch_once(&onceToken, ^{

      // 這裏面的代碼,在程序運行過程當中,永遠只會執行1次

  });

 

 九 單例模式(懶漢式)

  1.ARC

  

@interface HMDataTool : NSObject
  
+ (instancetype)sharedDataTool;  
@end

@implementation HMDataTool   // 用來保存惟一的單例對象   static id _instace;   + (id)allocWithZone:(struct _NSZone *)zone   {    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{    _instace = [super allocWithZone:zone];    });    return _instace;   }   + (instancetype)sharedDataTool   {    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{    _instace = [[self alloc] init];   });   return _instace;   }   - (id)copyWithZone:(NSZone *)zone   {    return _instace;   }   @end

 

 2 非ARC

 2.非ARC
  @interface HMDataTool : NSObject
  + (instancetype)sharedDataTool;
  @end
 

  @implementation HMDataTool

  // 用來保存惟一的單例對象
  static id _instace;

  + (id)allocWithZone:(struct _NSZone *)zone
  {      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
          _instace = [super allocWithZone:zone];
      });
      return _instace;
  }

  + (instancetype)sharedDataTool
  {
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{

          _instace = [[self alloc] init];

      });
      return _instace;
  }

  - (id)copyWithZone:(NSZone *)zone
  {
      return _instace;
  }

  - (oneway void)release {

  }

  - (id)retain {
      return self;
  }

  - (NSUInteger)retainCount {
      return 1;
  }

  - (id)autorelease {
      return self;
  }
 @end

 

 

十 NSOperation和NSOperationQueue

  1.隊列的類型

  1> 主隊列

  * [NSOperationQueue mainQueue]

  * 添加到"主隊列"中的操做,都會放到主線程中執行

 

  2> 非主隊列

  * [[NSOperationQueue alloc] init]

  * 添加到"非主隊列"中的操做,都會放到子線程中執行

 

  2.隊列添加任務

  * - (void)addOperation:(NSOperation *)op;

  * - (void)addOperationWithBlock:(void (^)(void))block;

 

  3.常見用法

  1> 設置最大併發數

- (NSInteger)maxConcurrentOperationCount;

- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

  2> 隊列的其餘操做

  * 取消全部的操做

- (void)cancelAllOperations;

  * 暫停全部的操做

[queue setSuspended:YES];

  * 恢復全部的操做  

[queue setSuspended:NO];

 

  4.操做之間的依賴(面試題)

  * NSOperation之間能夠設置依賴來保證執行順序

  * [operationB addDependency:operationA];

  // 操做B依賴於操做A,等操做A執行完畢後,纔會執行操做B

  * 注意:不能相互依賴,好比A依賴B,B依賴A

  * 能夠在不一樣queue的NSOperation之間建立依賴關係

 

  5.線程之間的通訊

  

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

  [queue addOperationWithBlock:^{

      // 1.執行一些比較耗時的操做

    
      // 2.回到主線程

      [[NSOperationQueue mainQueue] addOperationWithBlock:^{  

        
      }];

  }];

 

 

十一 從其餘線程回到主線程的方式

  

//perform...

  [self performSelectorOnMainThread:<#(SEL)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>];

 
//GCD

  dispatch_async(dispatch_get_main_queue(), ^{

  });

 
//NSOperationQueue

  [[NSOperationQueue mainQueue] addOperationWithBlock:^{

    

  }];

 

 

十二 判斷編譯器的環境:ARC仍是MRC?

  #if __has_feature(objc_arc)

  // 當前的編譯器環境是ARC

 

  #else

  // 當前的編譯器環境是MRC

 

  #endif

 

十三 類的初始化方法

  1.+(void)load

  * 當某個類第一次裝載到OC運行時系統(內存)時,就會調用

  * 程序一啓動就會調用

  * 程序運行過程當中,只會調用1次

 

  2.+(void)initialize

  * 當某個類第一次被使用時(好比調用了類的某個方法),就會調用

  * 並不是程序一啓動就會調用

 

  3.在程序運行過程當中:1個類中的某個操做,只想執行1次,那麼這個操做放到+(void)load方法中最合適

 

十四 第三方框架的使用建議

  1.用第三方框架的目的

  1> 開發效率:快速開發,人家封裝好的一行代碼頂本身寫的N行

  2> 爲了使用這個功能最牛逼的實現

 

  2.第三方框架過多,不少壞處(忽略不計)

  1> 管理、升級、更新

  2> 第三方框架有BUG,等待做者解決

  3> 第三方框架的做者不幸去世、中止更新(潛在的BUG無人解決)

  4> 感受:本身好水

 

  3.好比

  流媒體:播放在線視頻、音頻(邊下載邊播放)

  很是瞭解音頻、視頻文件的格式

  每一種視頻都有本身的解碼方式(C\C++)

 

  4.總結

  1> 站在巨人的肩膀上編程

  2> 沒有關係,使勁用那麼比較穩定的第三方框架

 

十五 cell的圖片下載

  1.面試題

  1> 如何防止一個url對應的圖片重複下載

  * 「cell下載圖片思路 – 有沙盒緩存」

 

  2> SDWebImage的默認緩存時長是多少?

  * 1個星期

 

  2.SDWebImage

  1> 經常使用方法

  

- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;

- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;

- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;

- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options   progress:  (SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;

 

 

  2> 內存處理:當app接收到內存警告時

  

/**
當app接收到內存警告
*/

  - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application

  {
    SDWebImageManager *mgr = [SDWebImageManager sharedManager];

      // 1.取消正在下載的操做

      [mgr cancelAll];

      // 2.清除內存緩存

      [mgr.imageCache clearMemory];

  }

 

  3> SDWebImageOptions

  * SDWebImageRetryFailed : 下載失敗後,會自動從新下載

  * SDWebImageLowPriority : 當正在進行UI交互時,自動暫停內部的一些下載操做

  * SDWebImageRetryFailed | SDWebImageLowPriority : 擁有上面2個功能

相關文章
相關標籤/搜索