前面介紹了多線程中常用的GCD,鏈接:IOS多線程網絡之GCD,這次介紹一下多線程網絡中的另一個好用的技術NSOperation
簡介NSOperation和GCD差不多,但是NSOperation更加的面向對象,相當於對GCD的一個封裝,NSOperation本身是一個抽象類,不具有封裝操作的能力,即定義一個NSOperation對象不能進行多線程操作,要想實現操作,必須要使用到它的子類:NSInvocationOperation或NSBlockOperation,但是在使用其進行多線程操作的時候,必須先將其加入到NSOperationQueue隊列中
使用方法 NSOperationQueueNSOperationQueue隊列類似於GCD中的主隊列,GCD中隊列分為:主隊列,串行隊列,並行隊列,而NSOperationQueue只有兩種:主隊列,非主隊列
主隊列NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
加入到主隊列的任務和GCD相同,不同創建新的線程,任務順序執行
非主隊列NSOperationQueue *queue = [[NSOperationQueue alloc] init];
加入到非主隊列的任務會自動創建新的線程執行任務,任務並行執行,加入到隊列中的任務不用再調用start方法來執行,系統會創建線程自動執行
NSInvocationOperationNSInvocationOperation直接使用init的創建方法,需要實現自定義的方法
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithtarget:self selector:@selector(click1) object:nil];
定義好對象之後,調用start方法執行任務,此時定義的所有對象都是同步操作的,即不會開啟新的線程執行任務
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithtarget:self selector:@selector(click1) object:nil];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithtarget:self selector:@selector(click2) object:nil];
NSInvocationOperation *op3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(click3) object:nil];
[op1 start];
[op2 start];
[op3 start];
執行結果:
但是當我們將對象加入到NSOperationQueue隊列中後,即可開啟新的線程執行任務
[queue addOperations:@[op1, op2, op3] waitUntilFinished:YES];
執行結果:
NSBlockOperation采用block的創建方式,直接在block塊中書寫任務
NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block1-------%@",[NSThread currentThread]);
}];
定義好之後,調用start方法執行任務,但是同樣的此時不會開啟新的線程
NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block1-------%@",[NSThread currentThread]);
}];
NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block2-------%@",[NSThread currentThread]);
}];
NSBlockOperation *block3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block3-------%@",[NSThread currentThread]);
}];
[block1 start];
[block2 start];
[block3 start];
執行結果:
當我們將其加入到隊列中之後,即可開啟新的線程
[queue addOperations:@[block1, block2, block3] waitUntilFinished:YES];
執行結果:
使用NSBlockOperation的時候,我們還可以對其追加block任務,同樣可以並發執行
[block1 addExecutionBlock:^{
NSLog(@"block11--------%@",[NSThread currentThread]);
}];
執行結果:
當然,我們使用NSBlockOperation的時候也可以創建一個沒有任務的NSBlockOperation對象,然後對其進行追加.
那麼問題來了,將兩種對象加入到隊列中能不能實現並行執行呢?
答案是可以
[queue addOperations:@[block1, block2, block3, op1, op2, op3] waitUntilFinished:YES];
執行結果:
NSOperation和GCD的一個區別就是可以設置並發數量,我們可以通過設置並發數量,來限制是否進行多線程操作
queue.maxConcurrentOperationCount = 5;
和GCD的區別
NSOperation既然是對GCD的封裝,那麼必然有著GCD不能實現的功能
取消任務當我們設置了兩個任務A和B,如果B要在A任務完成後使用A獲得的數據進行任務,但是A任務因為網絡問題執行失敗,那麼我們應該取消B任務來節省性能
//取消NSOperation任務
[op1 cancel];
//取消NSOperationQueue剩余的NSOperation任務
[queue cencelAllOperations]
設置依賴關系
還是A和B的例子,如果B必須要在A執行完之後再進行,如果是在主線程中,這個肯定是實現的,但是我們如果還想實現多線程,還是滿足條件,怎麼辦呢?GCD中可以使用柵欄函數來實現這一功能,但是NSOperation更為簡單,直接設置依賴即可,前提是兩個任務都在隊列中
//op2在op1執行完成之後執行
[op2 addDependency:op1];
注意:兩者不能相互依賴,即op1依賴於op2,op2依賴於op1,這樣會導致死鎖
隊列的暫停與恢復這個更加簡單,直接設置屬性即可
[queue setSuspended:YES];//YES代表暫停隊列,NO代表恢復隊列
定義任務優先級
在GCD中,我們可以定義隊列執行的優先級,但是在NSOperation中,我們可以定義任務的優先級,關於任務優先級,有五種類型:
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
NSOperationQueuePriorityVeryLow = -8L,
NSOperationQueuePriorityLow = -4L,
NSOperationQueuePriorityNormal = 0,
NSOperationQueuePriorityHigh = 4,
NSOperationQueuePriorityVeryHigh = 8
};
我們可以直接設置任務對象的優先級,但是設置了優先級一定就能保證優先執行嗎?如果多個任務對象的優先級相同會怎麼樣呢?
op1.queuePriority = NSOperationQueuePriorityVeryHigh;
op2.queuePriority = NSOperationQueuePriorityVeryHigh;
op3.queuePriority = NSOperationQueuePriorityVeryHigh;
[queue addOperations:@[op1, op2, op3] waitUntilFinished:YES];
執行結果:
恩?好像是誰先設置誰先執行?別高興的太早,我們再次運行試試看
這個時候就不一樣了,這個需要注意
通過兩篇文章的總結,我們可以注意到GCD通過block為單位,結構和C語言相似,更加的底層,處理相對較快,且使用簡便,設置單個任務比NSOperation要簡單.
而NSOperation可以設置並發數來限制線程,任務執行的順序且任務可以被取消,隊列可以暫停和恢復,更加的靈活.,對於多個任務的處理比GCD要更好控制.
歡迎來到我的博客,我是AnICoo1,我喂自己袋鹽
有錯誤請評論指出或聯系我,不勝感激!
個人郵箱:[email protected]
【iOS多線程網絡之NSOperation】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!