多線程&NSObject&NSThread&NSOperation&GCD

一、NSThread 每一個NSThread對象對應一個線程,量級較輕(真正的多線程) 如下兩點是蘋果專門開發的「併發」技術,使得程序員能夠再也不去關心線程的具體使用問題 二、NSOperation/NSOperationQueue 面向對象的線程技術 三、GCD —— Grand Central Dispatch(派發) 是基於C語言的框架,能夠充分利用多核,是蘋果推薦使用的多線程技術程序員

以上這三種編程方式從上到下,抽象度層次是從低到高的,抽象度越高的使用越簡單,也是Apple最推薦使用的。可是就目前而言,iOS的開發者,須要瞭解三種多線程技術的基本使用過程。由於不少框架技術分別使用了不一樣多線程技術。編程

NSThread: 優勢:NSThread 比其餘兩個輕量級,使用簡單 缺點:須要本身管理線程的生命週期、線程同步、加鎖、睡眠以及喚醒等。線程同步對數據的加鎖會有必定的系統開銷 NSOperation: 不須要關心線程管理,數據同步的事情,能夠把精力放在本身須要執行的操做上 NSOperation是面向對象的 GCD: Grand Central Dispatch是由蘋果開發的一個多核編程的解決方案。iOS4.0+才能使用,是替代NSThread, NSOperation的高效和強大的技術 GCD是基於C語言的多線程

NSObject的多線程方法——後臺線程併發

  • (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg 一般,因爲線程管理相對比較繁瑣,而不少耗時的任務又沒法知道其準確的完成時間,所以可使用performSelectorInBackground方法直接新建一個後臺線程,並將選擇器指定的任務在後臺線程執行,而無需關心具體的NSThread對象 提示: performSelectorInBackground方法自己是在主線程中執行的,而選擇器指定的方法是在後臺線程中進行的 使用performSelectorInBackground方法調用的任務能夠更新UI界面 在大型交互式遊戲中框架

  • (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; 若是要更新UI界面,能夠在後臺線程中調用performSelectorOnMainThread方法 提示:儘管使用performSelectorInBackground方法調用的任務能夠更新UI界面,可是在實際開發中,涉及到UI界面的更新操做,仍是要使用performSelectorOnMainThread方法,以免沒必要要的麻煩異步

    <!-- lang: cpp -->async

    - (IBAction)bigTask

{ // 本方法中的全部代碼都是在主線程中執行的 // NSObject多線程技術 NSLog(@"執行前->%@", [NSThread currentThread]);函數

// performSelectorInBackground是將bigDemo的任務放在後臺線程中執行
[self performSelectorInBackground:@selector(bigDemo) withObject:nil];

NSLog(@"執行後->%@", [NSThread currentThread]);

// [self bigDemo];spa

NSLog(@"執行完畢");

}線程

NSThread建立線程方法:

  • (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;
  • (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument; 參數說明: selector:線程執行的方法,只能有一個參數,不能有返回值 target:selector消息發送的對象 argument:傳輸給target的惟一參數,也能夠是nil

    <!-- lang: cpp -->

    // 成員方法 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(bigDemo) object:nil];

    // 啓動start線程 [thread start];

NSOperation & NSOperationQueue NSOperation的兩個子類 NSInvocationOperation NSBlockOperation 工做原理: 用NSOperation封裝要執行的操做 將建立好的NSOperation對象放NSOperationQueue中 啓動OperationQueue開始新的線程執行隊列中的操做 注意事項: 使用多線程時一般須要控制線程的併發數,由於線程會消耗系統資源,同時運行的線程過多,系統會變慢 使用如下方法能夠控制併發的線程數量: (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

<!-- lang: cpp -->
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(opAction) object:nil];

// 若是使用start,會在當前線程啓動操做

// [op1 start];

// 1. 一旦將操做添加到操做隊列,操做就會啓動
[_queue addOperation:op1];

<!-- lang: cpp -->
// 用block的最大好處,能夠將一組相關的操做,順序寫在一塊兒,便於調試以及代碼編寫
[_queue addOperationWithBlock:^{
    NSLog(@"%@", [NSThread currentThread]);
    
    // 模擬延時
    [NSThread sleepForTimeInterval:1.0f];
    
    // 模擬獲取到圖像
    UIImage *image = [UIImage imageNamed:@"頭像1"];
    
    // 設置圖像,在主線程隊列中設置
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        _imageView.image = image;
    }];
}];

GCD是基於C語言的框架 工做原理: 讓程序平行排隊的特定任務,根據可用的處理資源,安排它們在任何可用的處理器上執行任務 要執行的任務能夠是一個函數或者一個block 底層是經過線程實現的,不過程序員能夠沒必要關注實現的細節 GCD中的FIFO隊列稱爲dispatch queue,能夠保證先進來的任務先獲得執行 dispatch_notify 能夠實現監聽一組任務是否完成,完成後獲得通知 GCD隊列: 全局隊列:全部添加到主隊列中的任務都是併發執行的 串行隊列:全部添加到串行隊列中的任務都是順序執行的 主隊列:全部添加到主隊列中的任務都是在主線程中執行的

全局隊列(可能會開啓多條線程) 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();

異步操做 dispatch_async 在其餘線程執行任務,會開啓新的線程 異步方法沒法肯定任務的執行順序 同步操做 dispatch_sync 在當前在當前線程執行任務,不開啓新的線程 同步操做與隊列無關 同步方法會依次執行,可以決定任務的執行順序 更新界面UI時,最好使用同步方法

GCD的優勢: 充分利用多核 全部的多線程代碼集中在一塊兒,便於維護 GCD中無需使用@autoreleasepool 若是要順序執行,可使用dispatch_sync同步方法 dispatch_async沒法肯定任務的執行順序

<!-- lang: cpp -->
 // 1. 隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

// 2. 將任務異步(併發)執行
dispatch_async(queue, ^{
    NSLog(@"a->%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
    NSLog(@"b->%@", [NSThread currentThread]);
});

dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"main - > %@", [NSThread currentThread]);
});
相關文章
相關標籤/搜索