NSOperationQueue與GCD是伯仲之間嗎
事實(shí):GCD是面向底層的C語言的API, NSOperationQueue是基于GCD面向OC的封裝
結(jié)果:
1)GCD執(zhí)行效率更高
2)GCD只支持FIFO的隊(duì)列,而NSOperationQueue可以通過設(shè)置最大并發(fā)數(shù),設(shè)置優(yōu)先級,添加依賴關(guān)系等調(diào)整執(zhí)行順序
3)NSOperationQueue甚至可以跨隊(duì)列設(shè)置依賴關(guān)系,但是GCD只能通過設(shè)置串行隊(duì)列,或者在隊(duì)列內(nèi)添加barrier(dispatch_barrier_async)任務(wù),才能控制執(zhí)行順序,較為復(fù)雜
- NSOperationQueue因?yàn)槊嫦驅(qū)ο螅灾С諯VO,可以監(jiān)測operation是否正在執(zhí)行(isExecuted)、是否結(jié)束(isFinished)、是否取消(isCanceld)
NSOperationQueue的API
- start,開啟任務(wù),當(dāng)把NSOperation添加到NSOperationQueue中去后,隊(duì)列會在操作中調(diào)用start方法。這里沒有添加到NSOperationQueue中,手動(dòng)start,默認(rèn)在主隊(duì)列中
//start 開啟任務(wù),默認(rèn)主隊(duì)列
NSBlockOperation *operationOne = [NSBlockOperation blockOperationWithBlock:^{\
for (int i=0; i<3; i++) {
NSLog(@"=%@=====%d",[NSThread currentThread],i);
}
}];
[operationOne start];
- addOperation或者addOperationWithBlock , 只要是自己創(chuàng)建的隊(duì)列,就會在子線程中執(zhí)行,默認(rèn)并發(fā),設(shè)置maxConcurrentOperationCount為 1 時(shí)是串行執(zhí)行
//主隊(duì)列
NSOperationQueue *mainqueue = [NSOperationQueue mainQueue];
//自己創(chuàng)建的隊(duì)列
NSOperationQueue *customQueue = [[NSOperationQueue alloc]init];
customQueue.maxConcurrentOperationCount = 2; //最大并發(fā)數(shù)
//只要是自己創(chuàng)建的隊(duì)列,就會在子線程中執(zhí)行,默認(rèn)并發(fā),設(shè)置maxConcurrentOperationCount時(shí)是串行執(zhí)行
[customQueue addOperationWithBlock:^{
//向隊(duì)列中添加block異步任務(wù)
for (int i=3; i<6; i++) {
NSLog(@"=%@=====%d",[NSThread currentThread],i);
}
}];
[customQueue addOperationWithBlock:^{
//向隊(duì)列中添加block異步任務(wù)
for (int i=6; i<9; i++) {
NSLog(@"=%@=====%d",[NSThread currentThread],i);
}
}];
//添加 NSInvocationOperation
[customQueue addOperation:[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(invocationOperationDeal) object:nil]];
- 隊(duì)列控制API
//將隊(duì)列中任務(wù)暫停
customQueue.suspended = YES;
//將隊(duì)列中任務(wù)恢復(fù)執(zhí)行
customQueue.suspended = NO;
//取消隊(duì)列中的所有任務(wù)
[customQueue cancelAllOperations];
- addDependency 添加依賴,removeDependency刪除依賴,
//任務(wù)之間添加依賴,比如當(dāng)前一個(gè)任務(wù)的返回結(jié)果 是 后一個(gè)任務(wù)的所需元素時(shí)
NSBlockOperation *blockOp1 = [NSBlockOperation blockOperationWithBlock:^{
//計(jì)算出小明的臉部數(shù)據(jù)
}];
NSBlockOperation *blockOp2 = [NSBlockOperation blockOperationWithBlock:^{
//計(jì)算出小明的頭圍數(shù)據(jù)
}];
NSBlockOperation *blockOp3 = [NSBlockOperation blockOperationWithBlock:^{
// 制作出小明的頭部模型
}];
[blockOp3 addDependency:blockOp1];
[blockOp3 addDependency:blockOp2]; //blockOp3的操作依賴于 1 和 2 的結(jié)果
[customQueue addOperations:@[blockOp1,blockOp2,blockOp3] waitUntilFinished:NO];
- setQueuePriority,設(shè)置優(yōu)先級, 當(dāng)你添加一個(gè)操作到一個(gè)隊(duì)列時(shí),在對操作調(diào)用start之前,NSOperationQueue會瀏覽所有的操作,具有較高優(yōu)先級的操作會優(yōu)先執(zhí)行,具有相同優(yōu)先級的操作會按照添加到隊(duì)列中順序執(zhí)行。
[a setQueuePriority:NSOperationQueuePriorityVeryLow];
一共有四個(gè)優(yōu)先級:
NSOperationQueuePriorityLow,
NSOperationQueuePriorityNormal,
NSOperationQueuePriorityHigh,
NSOperationQueuePriorityVeryHigh
- setCompletionBlock 設(shè)置完成回調(diào)
[blockOp2 setCompletionBlock:^{
//blockOp2任務(wù)執(zhí)行完成,此block在主線程執(zhí)行
}];
小結(jié)
1、實(shí)際項(xiàng)目開發(fā)中,很多時(shí)候只是會用到異步操作,不會有特別復(fù)雜的線程關(guān)系管理,所以蘋果推崇的且優(yōu)化完善、運(yùn)行快速的GCD是首選
2、如果涉及到類似多線程并發(fā)下載,這種多任務(wù)還要控制任務(wù)進(jìn)度的情況,可能就要考慮使用易于管理的NSOperationQueue了,關(guān)于自定義NSOperation的內(nèi)容,后續(xù)我會另寫一篇文章的,繼續(xù)學(xué)習(xí)
3、另外不論是GCD還是NSOperationQueue,我們接觸的都是任務(wù)和隊(duì)列,都沒有直接接觸到線程這個(gè)東東,事實(shí)上線程管理也的確不需要我們操心,系統(tǒng)對于線程的創(chuàng)建,調(diào)度管理和釋放都做得很好。但是有一個(gè)線程類NSThread可以滿足我們對于線程的好奇心,但是NSThread需要我們自己去管理線程的生命周期,還要考慮線程同步、加鎖問題,造成一些性能上的開銷
附圖,這張圖如此之精辟,讓我久久挪不開眼睛
