標籤:
iOS多線程技術主要分配NSThread、NSOperation和GCD。下邊來簡單的介紹一下吧。
隨性一點,就不按照順序來了。所以先介紹一下NSOperation。
------------------------------------------------------------------------------NSOperation------------------------------------------------------------------------------
NSBlockOperation:
它是NSOperation的一個具體的子類,它管理著並發執行的一個或者多個塊操作。你可以使用這個對象一次執行多個連續的塊,而沒有必要去為每一個操作建立分開的操作對象。當執行超過一個block時,操作自己在所有塊執行完畢後結束。
NSInvocationOperation:
它是NSOperation的一個具體子類,它管理執行一個單獨的封裝的任務作為一個調用。你可以使用這個類開始一個調用指定對象的選取器操作。這個類實現的是非並行作業。
NSOperationQueue:
該類控制一套NSOperation對象的執行。當把operation添加到隊列,它會一直存在在該隊列中,直到確信它取消或者結束執行它的任務。在queue(還沒有執行)中的operation都是自己組織執行根據優先順序和相互作用對象依賴。一個application可能會建立多個操作隊列,然後執行他們其中的任何一個操作。
需要注意:NSOperationQueue為NSOperation分配不同的線程來執行。
- (void)testOperationQueue { NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOperation1:%p",[NSThread currentThread]); }]; NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOperation2:%p",[NSThread currentThread]); }]; NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOperation3:%p",[NSThread currentThread]); }]; [operationQueue addOperation:blockOperation1]; [operationQueue addOperation:blockOperation2]; [operationQueue addOperation:blockOperation3];}
上面是一個簡單的測試程式,我們可以看到在一個NSOperationQueue中添加了三個塊操作。然後執行結果如下:
第一次執行:
2015-08-21 09:25:24.954 GCD[1251:280098] main Thread is 0x7ff3fc111ac02015-08-21 09:25:24.955 GCD[1251:280205] blockOperation3:0x7ff3f8f09ea02015-08-21 09:25:24.955 GCD[1251:280206] blockOperation1:0x7ff3fc31dd502015-08-21 09:25:24.955 GCD[1251:280207] blockOperation2:0x7ff3f8f09dc0
可見NSOperationQueue為NSBlockOperation分配了不同的線程。而是是並行作業。也就是說NSOperation預設是並發執行的,要想串列執行很簡單,只需要設定一下NSOperationQueue的一個屬性即可:
operationQueue.maxConcurrentOperationCount = 1;
該屬性來控制NSOperationQueue的最大並發數量,當設定為1是就是串列執行了。
接下來看看下邊的代碼:
- (void)testOperationQueue {// NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOperation1:%p",[NSThread currentThread]); }]; NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOperation2:%p",[NSThread currentThread]); }]; NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOperation3:%p",[NSThread currentThread]); }];// operationQueue.maxConcurrentOperationCount = 1;// [operationQueue addOperation:blockOperation1];// [operationQueue addOperation:blockOperation2];// [operationQueue addOperation:blockOperation3]; [blockOperation1 start]; [blockOperation2 start]; [blockOperation3 start];}
我沒有將NSBlockOperation放到NSOperationQueue中,而是直接自己調用了start方法,此時會有什麼結果呢???????
看結果:
2015-08-21 09:33:21.451 GCD[1423:316980] main Thread is 0x7fe178a11a702015-08-21 09:33:21.451 GCD[1423:316980] blockOperation1:0x7fe178a11a702015-08-21 09:33:21.452 GCD[1423:316980] blockOperation2:0x7fe178a11a702015-08-21 09:33:21.452 GCD[1423:316980] blockOperation3:0x7fe178a11a70
結果表明:當我直接去調用NSOperation的start方法時,此時所有的NSOperation都是在主線程上執行的。因為他們的線程地址一樣。而且是順序執行的。
此外,NSOperation還提供了cancel方法,不過這裡cancel只能取消狀態為Ready、Finish的NSOperation,不能取消正在執行的操作。
再此外,NSOperation還提供了addDependency:方法。
addDependency方法的作用是使接收者一欄指定操作的完成。接收者不考慮去執行它自己直到所有它的依賴操作結束執行。如果接收者準備執行它的任務,添加依賴就沒有實際性的影響了。該方法可能改變接收者的isReady和相依性屬性。舉個例子:
[operation3 addDependency:operation2]; //操作3依賴於操作2
如上邊那句代碼,意思是operation3依賴於operation2的操作,如果operation2沒有執行,並且operation3還沒有準備執行它的任務,那麼他們的執行順序一定是operation2先執行,然後operation3後執行。
------------------------------------------------------NSBlockOperation結束---------------------------------------------------------------------------------
NSInvocation
上邊已經介紹了這個類的大概作用,現在來看看它的使用:
- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"main Thread is %p",[NSThread mainThread]); [self nsInvocationOperationTest];}- (void)nsInvocationOperationTest { NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(test) object:nil]; [operation start];}- (void)test { NSLog(@"operation:%p",[NSThread currentThread]);}
執行結果如下:
2015-08-21 10:52:23.359 GCD[2193:756929] main Thread is 0x7f9442e07fe02015-08-21 10:52:23.360 GCD[2193:756929] operation:0x7f9442e07fe0
操作對象預設在主線程中執行,這個和NSBlockOperation一樣。如果是多個則是串列執行。如果我們沒有把它放在NSOperationQueue中,都是在主線程執行。
NSOperation總結:
NSBlockOperation可以單獨的調用start執行,但是此時都是再主隊列中執行的。
NSBlockOperatioin可以添加到NSOperationQueue中執行,此時都是建立的線程執行。可以通過cancel取消ready和執行完畢的線程和addDependency設定線程依賴。
-------------------------------------------------------------------------------------NSOperation結束-------------------------------------------------------------------------------------
NSThread
它是比NSOperation和GCD都要輕量級的線程。
它有兩種直接建立形式
[[NSThread alloc] initWithTarget:<#(id)#> selector:<#(SEL)#> object:<#(id)#>]; [NSThread detachNewThreadSelector:<#(SEL)#> toTarget:<#(id)#> withObject:<#(id)#>]
也就是第一個種使用執行個體方法。initWithTawrget...那個。第二個是使用的類方法。
第一種建立的線程是先建立線程對象,然後在運行線程操作,需要手動調用start方法。
第二種是直接建立線程並且開始運行線程。
還有一種不顯式建立線程的方法:
[self performSelector:<#(SEL)#> withObject:<#(id)#>]
就是使用NSObject的類方法。
---------------------------------------------------------------------------NSThread就這麼多吧---------------------------------------------------------------------------
至於GCD,請參考這裡
現在來對比一下三者:
NSThread:
優點:比其他兩個輕量級、使用簡單
缺點,需要自己管理線程的生命週期、線程同步、加鎖、睡眠等。
NSOperation:
優點:不需要關心線程管理以及資料同步
NSOperation是物件導向的。
GCD:
iOS4.0+才能使用,是替代NSThread/NSOperation的高效和強大的技術。
它是基於C語言的。
------------------------------------------------------------------先介紹這麼多吧------------------------------------------------------------------
addDependency
iOS多線程技術