iOS多線程編程

iOS提供了三種多線程編程的方式:

  • 使用NSThread實現多線程;
  • 使用NSOperation與NSOperationQueue實現多線程;
  • 使用GCD實現多線程實現多線程。

一、使用NSThread實現多線程

iOS系統使用NSThread代表線程,創建新線程也就是創建NSThread對象,創建NSThread的方法有兩種。

(1)-(id) initWithTarget:selector:object:  //創建一個新線程對象;

<span style="font-size:14px;">// 創建線程對象
NSThread *thread = [[NSThread alloc]initWithTarget:self
				          selector:@selector(run) object:nil];
// 啓動新線程
[thread start];</span>

(2)+(void) detachNewThreadSelector:toTarget:withObject:  //創建並啓動一個新線程(在OX10.5之前只能通過這種方式來啓動一個線程)

<span style="font-size:14px;">// 創建並啓動新線程
[NSThread detachNewThreadSelector:@selector(run) toTarget:self
				               withObject:nil];</span>
以上兩種方法的本質都是將target對象的selector方法轉換成線程執行體。

二、使用NSOperation與NSOperationQueue實現多線程

NSOperationQueue:代表一個FIFO隊列,負責管理系統提交的多個NSOperation,NSOperationQueue底層維護一個線程池,會按順序啓動線程來執行提交給該隊列的NSOperation任務。

NSOperation:代表一個多線程任務,有兩個子類:NSInvocationOperation和NSBlockOperation。創建NSOperation對象的方法有兩種,一種是創建自定義類繼承NSOperation,另一種是直接使用NSOperation的兩個子類。

使用NSOperation與NSOperationQueue實現多線程分兩步:

(1)創建NSOperationQueue隊列,併爲該隊列設置屬性;

<span style="font-size:14px;">NSOperationQueue* queue = [[NSOperationQueue alloc]init];
// 設置該隊列最多支持10條併發線程
queue.maxConcurrentOperationCount = 10;</span>

(2)創建NSOperation子類對象,並將該對象提交給NSOperationQueue隊列

<span style="font-size:14px;">// 將NSOperation的子類的實例提交給NSOperationQueue
[queue addOperation:operation];</span>

三、使用GCD實現多線程實現多線程

GCD的基本概念就是dispatch queue。dispatch queue是一個對象,它可以接受任務,並將任務以先到先執行的順序來執行。dispatch queue可以是併發的或串行的,併發任務會像NSOperationQueue那樣基於系統負載來合適地併發進行,串行隊列同一時間只執行單一任務。關於GCD的具體描述請參考Apple官方文檔

GCD中有三種隊列類型:main queue、global queues和用戶隊列。

(1)main queue:與主線程功能相同,提交至main queue的任務會在主線程中執行,mainqueue可以調用dispatch_get_main_queue() 來獲得。因爲main queue是與主線程相關的,所以這是一個串行隊列。

(2)全局隊列:是併發隊列,並由整個進程共享。進程中存在四個全局隊列:高、中(默認)、低和後臺四個優先級隊列,可以調用dispatch_get_global_queue()函數傳入優先級來訪問指定的全局隊列。

(3)用戶隊列:是用函數 dispatch_queue_create() 創建的隊列,是串行的,可以用來完成同步機制。這裏需要注意的是,使用dispatch_queue_create() 創建的 dispatch queue 對象不受ARC機制的管理(全局隊列和 main queue 不需要手動管理),需要手動進行內存管理,使用 dispatch_release 和 dispatch_retain 函數來操作引用計數。

使用GCD實現多線程也只有兩步:

(1)創建隊列;

(2)將任務提交給隊列。

dispatch_async(提交異步任務)、dispatch_sync(提交同步任務)

向一個隊列提交任務很簡單:調用dispatch_async函數,傳入一個隊列和一個block。隊列會在輪到這個block執行時執行這個block的代碼。

如果希望在任務完成時更新UI界面,也就意味着需要在主線程中執行一些代碼UI操作必須在主線程中執行)。你可以簡單地完成這個任務——使用嵌套的dispatch,在外層中執行後臺任務,在內層中將任務dispatch到main queue。

<span style="font-size:14px;">dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
        [self goDoSomethingLongAndInvolved]; 
        dispatch_async(dispatch_get_main_queue(), ^{ 
            [textField setStringValue:@"Done doing something long and involved"]; 
        }); 
});</span>

假設有一段代碼在後臺執行,而它需要從界面控制層獲取一個值,可以使用__block類型修飾符,從執行中的block中獲取一個值。

使用嵌套的block來中止後臺線程,然後從主線程中獲取值,然後再將後期處理提交至後臺線程。

<span style="font-size:14px;">dispatch_queue_t bgQueue = myQueue; 
dispatch_async(dispatch_get_main_queue(), ^{ 
    NSString *stringValue = [[[textField stringValue] copy] autorelease]; 
    dispatch_async(bgQueue, ^{ 
        // use stringValue in the background now
        ...
    }); 
});</span>

發佈了37 篇原創文章 · 獲贊 22 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章