一格郁、NSOperation簡介
【官方網(wǎng)址】(https://developer.apple.com/documentation/foundation/nsoperation?language=occ)
NSOperation是蘋果提供給我們的一套多線程解決方案。實際上NSOperation是基于GCD更高一層的封裝锣尉,但是比GCD更簡單易用自沧、代碼可讀性也更高拇厢。
NSOperation需要配合NSOperationQueue來實現(xiàn)多線程孝偎。因為默認情況下邪媳,NSOperation單獨使用時系統(tǒng)同步執(zhí)行操作,并沒有開辟新線程的能力迅涮,只有配合NSOperationQueue才能實現(xiàn)異步執(zhí)行叮姑。1.他是一個抽象類,無法直接使用.但是我們可以使用它的子類.作為父類約束子類共有的屬性和方法
2.子類 - 操作默認是異步的.
NSBlockOperation
NSInvocationOperation
自定義NSOperation3.隊列 - 默認是并發(fā)的.
@interface NSOperationQueue : NSObject4.總結(jié)
GCD的核心 : 將任務添加到隊列
NSOperation的核心 : 將操作添加到隊列
二据悔、NSOperation使用步驟
1极颓、創(chuàng)建操作:先將需要執(zhí)行的操作封裝到一個 NSOperation 對象中
2、創(chuàng)建隊列:創(chuàng)建 NSOperationQueue 對象
3兵琳、將操作加入到隊列中:將 NSOperation 對象添加到 NSOperationQueue 對象中
三躯肌、為什么要使用 NSOperation清女、NSOperationQueue嫡丙?
1迄沫、可添加完成的代碼塊卦方,在操作完成后執(zhí)行盼砍。
2浇坐、添加操作之間的依賴關系近刘,方便的控制執(zhí)行順序介劫。
3案淋、設定操作執(zhí)行的優(yōu)先級踢京。
4黔帕、可以很方便的取消一個操作的執(zhí)行蹈丸。
5白华、使用 KVO 觀察對操作執(zhí)行狀態(tài)的更改:isExecuteing厦取、isFinished管搪、isCancelled霎箍。
NSOperation和NSOperationQueue的基本使用
1漂坏、使用子類NSInvocationOperation
// 1.創(chuàng)建NSInvocationOperation對象
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
// 2.調(diào)用start方法開始執(zhí)行操作
[op start];
- (void)run{
NSLog(@"------%@", [NSThread currentThread]);
}
輸出結(jié)果:
2017-11-20 10:41:16.521032+0800 test[5023:190051] ------<NSThread: 0x6040000662c0>{number = 1, name = main}
2顶别、使用子類NSBlockOperation
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
// 在主線程
NSLog(@"------%@", [NSThread currentThread]);
}];
[op start];
輸出結(jié)果:
2017-11-20 10:43:29.704281+0800 test[5145:202303] ------<NSThread: 0x60400006bac0>{number = 1, name = main}
我們同樣可以看到驯绎,在沒有使用NSOperationQueue剩失、單獨使用NSBlockOperation的情況下拴孤,NSBlockOperation也是在主線程執(zhí)行操作,并沒有開啟新線程涨椒。
但是蚕冬,NSBlockOperation還提供了一個方法addExecutionBlock:
囤热,通過addExecutionBlock:
就可以為NSBlockOperation添加額外的操作旁蔼,這些操作就會并發(fā)執(zhí)行棺聊。
- (void)blockOperation
{
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1------%@", [NSThread currentThread]);
}];
// 添加額外的任務
[op addExecutionBlock:^{
NSLog(@"2------%@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
NSLog(@"3------%@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
NSLog(@"4------%@", [NSThread currentThread]);
}];
[op start];
}
輸出結(jié)果:
2017-11-20 10:46:12.639798+0800 test[5279:215979] 1------<NSThread: 0x6000004624c0>{number = 3, name = (null)}
2017-11-20 10:46:12.639797+0800 test[5279:215842] 4------<NSThread: 0x60400007ac80>{number = 1, name = main}
2017-11-20 10:46:12.639797+0800 test[5279:215977] 2------<NSThread: 0x600000462500>{number = 5, name = (null)}
2017-11-20 10:46:12.639829+0800 test[5279:215976] 3------<NSThread: 0x604000464940>{number = 4, name = (null)}
可以看出,blockOperationWithBlock:
方法和addExecutionBlock:
方法所添加的操作是在多條線程中執(zhí)行的祟同。
3理疙、定義繼承自NSOperation的子類
先定義一個繼承自NSOperation的子類砖顷,重寫main方法
YSCOperation.h
#import <Foundation/Foundation.h>
@interface YSCOperation : NSOperation
@end
YSCOperation.m
#import "YSCOperation.h"
@implementation YSCOperation
/**
* 需要執(zhí)行的任務
*/
- (void)main
{
for (int i = 0; i < 2; ++i) {
NSLog(@"1-----%@",[NSThread currentThread]);
}
}
@end
然后使用的時候?qū)腩^文件YSCOperation.h择吊。
// 創(chuàng)建YSCOperation
YSCOperation *op1 = [[YSCOperation alloc] init];
[op1 start];
輸出結(jié)果:
2017-11-20 10:56:40.268238+0800 test[5904:271380] 1-----<NSThread: 0x604000069300>{number = 1, name = main}
2017-11-20 10:56:40.268409+0800 test[5904:271380] 1-----<NSThread: 0x604000069300>{number = 1, name = main}
可以看出:在沒有使用NSOperationQueue、單獨使用自定義子類的情況下粤攒,是在主線程執(zhí)行操作焕济,并沒有開啟新線程晴弃。
下邊我們簡單講講NSOperationQueue的創(chuàng)建上鞠。
2芍阎、創(chuàng)建隊列
和GCD中的并發(fā)隊列谴咸、串行隊列略有不同的是:NSOperationQueue一共有兩種隊列:主隊列、其他隊列岭佳。其中其他隊列同時包含了串行萧锉、并發(fā)功能驹暑。下邊是主隊列京办、其他隊列的基本創(chuàng)建方法和特點帆焕。
- 主隊列
凡是添加到主隊列中的任務(NSOperation)惭婿,都會放到主線程中執(zhí)行
NSOperationQueue *queue = [NSOperationQueue mainQueue];
- 其他隊列(非主隊列)
添加到這種隊列中的任務(NSOperation),就會自動放到子線程中執(zhí)行
同時包含了:串行叶雹、并發(fā)功能
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
3财饥、將任務加入到隊列中
前邊說了,NSOperation需要配合NSOperationQueue來實現(xiàn)多線程折晦。
那么我們需要將創(chuàng)建好的任務加入到隊列中去钥星。總共有兩種方法
-
- (void)addOperation:(NSOperation *)op;
需要先創(chuàng)建任務满着,再將創(chuàng)建好的任務加入到創(chuàng)建好的隊列中去
- (void)addOperationToQueue
{
// 1.創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2. 創(chuàng)建操作
// 創(chuàng)建NSInvocationOperation
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
// 創(chuàng)建NSBlockOperation
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1-----%@", [NSThread currentThread]);
}
}];
// 3. 添加操作到隊列中:addOperation:
[queue addOperation:op1]; // [op1 start]
[queue addOperation:op2]; // [op2 start]
}
- (void)run
{
for (int i = 0; i < 2; ++i) {
NSLog(@"2-----%@", [NSThread currentThread]);
}
}
輸出結(jié)果:
2017-11-20 11:06:47.458543+0800 test[6376:322141] 1-----<NSThread: 0x60400046c180>{number = 3, name = (null)}
2017-11-20 11:06:47.458580+0800 test[6376:322142] 2-----<NSThread: 0x60400046c200>{number = 4, name = (null)}
2017-11-20 11:06:47.458878+0800 test[6376:322142] 2-----<NSThread: 0x60400046c200>{number = 4, name = (null)}
2017-11-20 11:06:47.458885+0800 test[6376:322141] 1-----<NSThread: 0x60400046c180>{number = 3, name = (null)}
可以看出:NSInvocationOperation和NSOperationQueue結(jié)合后能夠開啟新線程宁改,進行并發(fā)執(zhí)行。NSBlockOperation和NSOperationQueue也能夠開啟新線程,進行并發(fā)執(zhí)行。
-
- (void)addOperationWithBlock:(void (^)(void))block;
無需先創(chuàng)建任務,在block中添加任務,直接將任務block加入到隊列中归敬。
- (void)addOperationWithBlockToQueue
{
// 1. 創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2. 添加操作到隊列中:addOperationWithBlock:
[queue addOperationWithBlock:^{
for (int i = 0; i < 2; ++i) {
NSLog(@"-----%@", [NSThread currentThread]);
}
}];
}
輸出結(jié)果:
2017-11-20 11:17:46.614125+0800 test[6880:376408] -----<NSThread: 0x60000026e500>{number = 3, name = (null)}
2017-11-20 11:17:46.614348+0800 test[6880:376408] -----<NSThread: 0x60000026e500>{number = 3, name = (null)}
可以看出addOperationWithBlock:和NSOperationQueue能夠開啟新線程,進行并發(fā)執(zhí)行。
3、控制串行執(zhí)行和并行執(zhí)行的關鍵
之前我們說過,NSOperationQueue創(chuàng)建的其他隊列同時具有串行、并發(fā)功能,上邊我們演示了并發(fā)功能,那么他的串行功能是如何實現(xiàn)的画恰?
這里有個關鍵參數(shù)maxConcurrentOperationCount
,叫做最大并發(fā)數(shù)。
- 最大并發(fā)數(shù):
maxConcurrentOperationCount
-
maxConcurrentOperationCount
默認情況下為-1,表示不進行限制,默認為并發(fā)執(zhí)行窃肠。 - 當
maxConcurrentOperationCount
為1時搀菩,進行串行執(zhí)行州既。 - 當
maxConcurrentOperationCount
大于1時蚌卤,進行并發(fā)執(zhí)行侮叮,當然這個值不應超過系統(tǒng)限制歹嘹,即使自己設置一個很大的值圆到,系統(tǒng)也會自動調(diào)整芽淡。
- (void)opetationQueue
{
// 創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 設置最大并發(fā)操作數(shù)
// queue.maxConcurrentOperationCount = 2;
queue.maxConcurrentOperationCount = 1; // 就變成了串行隊列
// 添加操作
[queue addOperationWithBlock:^{
NSLog(@"1-----%@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:0.01];
}];
[queue addOperationWithBlock:^{
NSLog(@"2-----%@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:0.01];
}];
[queue addOperationWithBlock:^{
NSLog(@"3-----%@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:0.01];
}];
[queue addOperationWithBlock:^{
NSLog(@"4-----%@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:0.01];
}];
[queue addOperationWithBlock:^{
NSLog(@"5-----%@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:0.01];
}];
[queue addOperationWithBlock:^{
NSLog(@"6-----%@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:0.01];
}];
}
最大并發(fā)數(shù)為1輸出結(jié)果:
2017-11-20 11:23:03.110467+0800 test[7122:398971] 1-----<NSThread: 0x600000464c00>{number = 3, name = (null)}
2017-11-20 11:23:03.120945+0800 test[7122:398973] 2-----<NSThread: 0x6040004614c0>{number = 4, name = (null)}
2017-11-20 11:23:03.131556+0800 test[7122:398971] 3-----<NSThread: 0x600000464c00>{number = 3, name = (null)}
2017-11-20 11:23:03.144559+0800 test[7122:398973] 4-----<NSThread: 0x6040004614c0>{number = 4, name = (null)}
2017-11-20 11:23:03.155188+0800 test[7122:398971] 5-----<NSThread: 0x600000464c00>{number = 3, name = (null)}
2017-11-20 11:23:03.165532+0800 test[7122:398973] 6-----<NSThread: 0x6040004614c0>{number = 4, name = (null)}最大并發(fā)數(shù)為2輸出結(jié)果:
2017-11-20 11:23:55.953623+0800 test[7179:404017] 2-----<NSThread: 0x60000027a940>{number = 4, name = (null)}
2017-11-20 11:23:55.953644+0800 test[7179:404018] 1-----<NSThread: 0x60000027aa00>{number = 3, name = (null)}
2017-11-20 11:23:55.964036+0800 test[7179:404015] 3-----<NSThread: 0x60400007fc80>{number = 5, name = (null)}
2017-11-20 11:23:55.964046+0800 test[7179:404016] 4-----<NSThread: 0x600000277240>{number = 6, name = (null)}
2017-11-20 11:23:55.974361+0800 test[7179:404018] 5-----<NSThread: 0x60000027aa00>{number = 3, name = (null)}
2017-11-20 11:23:55.974361+0800 test[7179:404017] 6-----<NSThread: 0x60000027a940>{number = 4, name = (null)}
可以看出:當最大并發(fā)數(shù)為1時,任務是按順序串行執(zhí)行的胚委。當最大并發(fā)數(shù)為2時鉴未,任務是并發(fā)執(zhí)行的核蘸。而且開啟線程數(shù)量是由系統(tǒng)決定的祟峦,不需要我們來管理。這樣看來,是不是比GCD還要簡單了許多绞绒?
4喻杈、操作依賴
NSOperation和NSOperationQueue最吸引人的地方是它能添加操作之間的依賴關系。比如說有A、B兩個操作夕玩,其中A執(zhí)行完操作,B才能執(zhí)行操作缔赠,那么就需要讓B依賴于A友题。具體如下:
- (void)addDependency
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1-----%@", [NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"2-----%@", [NSThread currentThread]);
}];
[op2 addDependency:op1]; // 讓op2 依賴于 op1嗤堰,則先執(zhí)行op1,在執(zhí)行op2
[queue addOperation:op1];
[queue addOperation:op2];
}
輸出結(jié)果:
2017-11-20 11:27:36.191658+0800 test[7363:423406] 1-----<NSThread: 0x600000261740>{number = 3, name = (null)}
2017-11-20 11:27:36.192122+0800 test[7363:423409] 2-----<NSThread: 0x600000261a80>{number = 4, name = (null)}
可以看到度宦,無論運行幾次踢匣,其結(jié)果都是op1先執(zhí)行,op2后執(zhí)行戈抄。
5离唬、一些其他方法
- -(void)cancel; NSOperation提供的方法,可取消單個操作
- -(void)cancelAllOperations; NSOperationQueue提供的方法划鸽,可以取消隊列的所有操作
- -(void)setSuspended:(BOOL)b; 可設置任務的暫停和恢復输莺,YES代表暫停隊列戚哎,NO代表恢復隊列
- -(BOOL)isSuspended; 判斷暫停狀態(tài)
- 注意:
1.這里的暫停和取消并不代表可以將當前的操作立即取消,而是當當前的操作執(zhí)行完畢之后不再執(zhí)行新的操作嫂用。
2.暫停和取消的區(qū)別就在于:暫停操作之后還可以恢復操作型凳,繼續(xù)向下執(zhí)行;而取消操作之后嘱函,所有的操作就清空了甘畅,無法再接著執(zhí)行剩下的操作。
6往弓、NSOperation優(yōu)先級
GCD中疏唾,任務(block)是沒有優(yōu)先級的,而隊列具有優(yōu)先級函似。和GCD相反槐脏,我們一般考慮 NSOperation 的優(yōu)先級。
NSOperation 有一個NSOperationQueuePriority 枚舉類型的屬性 queuePriority撇寞。
public enum NSOperationQueuePriority : Int {
case VeryLow
case Low
case Normal
case High
case VeryHigh
}
需要注意的是准给,NSOperationQueue 也不能完全保證優(yōu)先級高的任務一定先執(zhí)行。
queuePriority默認值是NSOperationQueuePriorityNormal重抖。根據(jù)實際需要我們可以通過調(diào)用queuePriority的setter方法修改某個操作的優(yōu)先級。
NSBlockOperation *blkop1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"執(zhí)行blkop1");
}];
NSBlockOperation *blkop2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"執(zhí)行blkop2");
}];
// 設置操作優(yōu)先級
blkop1.queuePriority = NSOperationQueuePriorityLow;
blkop2.queuePriority = NSOperationQueuePriorityVeryHigh;
NSLog(@"blkop1 == %@",blkop1);
NSLog(@"blkop2 == %@",blkop2);
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 操作添加到隊列
[queue addOperation:blkop1];
[queue addOperation:blkop2];
NSLog(@"%@",[queue operations]);
for (NSOperation *op in [queue operations]) {
NSLog(@"op == %@",op);
}
輸出結(jié)果:
2017-02-12 19:36:01.149 NSOperation[1712:177976] blkop1 == <NSBlockOperation: 0x608000044440>
2017-02-12 19:36:01.150 NSOperation[1712:177976] blkop2 == <NSBlockOperation: 0x6080000444d0>
2017-02-12 19:36:01.150 NSOperation[1712:177976] (
"<NSBlockOperation: 0x608000044440>",
"<NSBlockOperation: 0x6080000444d0>"
)
2017-02-12 19:36:01.150 NSOperation[1712:177976] op == <NSBlockOperation: 0x608000044440>
2017-02-12 19:36:01.150 NSOperation[1712:177976] op == <NSBlockOperation: 0x6080000444d0>
2017-02-12 19:36:01.150 NSOperation[1712:178020] 執(zhí)行blkop1
2017-02-12 19:36:01.151 NSOperation[1712:178021] 執(zhí)行blkop2
解析:
- 上面創(chuàng)建了兩個blockOperation并且分別設置了優(yōu)先級祖灰。顯然blkop1的優(yōu)先級低于blkop2的優(yōu)先級钟沛。然后調(diào)用了隊列的addOperation:方法使操作入隊。最后輸出結(jié)果證明局扶,操作在對列中的順序取決于addOperation:方法而不是優(yōu)先級恨统。
- 雖然blkop2優(yōu)先級高于blkop1,但是bloop1卻先于blkop2執(zhí)行完成三妈。所以畜埋,優(yōu)先級高的操作不一定先執(zhí)行完成。
- blkop2優(yōu)先級高于blkop1畴蒲,則代表blkop2先被執(zhí)行悠鞍,但是由于多線程的存在,blkop1可能會與blkop2并行執(zhí)行模燥。
注意:
(1)優(yōu)先級只能應用于相同queue中的operations咖祭。
(2)操作的優(yōu)先級高低不等于操作在隊列中排列的順序。換句話說蔫骂,優(yōu)先級高的操作不代表一定排在隊列的前面么翰。后入隊的操作有可能因為優(yōu)先級高而先被執(zhí)行。PS:操作在隊列中的順序取決于隊列的addOperation:方法辽旋。
(3)優(yōu)先級高只代表先被執(zhí)行浩嫌。不代表操作先被執(zhí)行完成檐迟。執(zhí)行完成的早晚還取決于操作耗時長短。
(4)優(yōu)先級不能替代依賴码耐,優(yōu)先級也絕不等于依賴追迟。優(yōu)先級只是對已經(jīng)準備好的操作確定其執(zhí)行順序。
(5)操作的執(zhí)行優(yōu)先滿足依賴關系伐坏,然后再滿足優(yōu)先級怔匣。即先根據(jù)依賴執(zhí)行操作,然后再從所有準備好的操作中取出優(yōu)先級最高的那一個執(zhí)行桦沉。
7每瞒、:waitUntilAllOperationsAreFinished
為了最佳的性能,你應該設計你的應用盡可能地異步操作,讓應用在Operation正在執(zhí)行時可以去處理其它事情纯露。如果需要在當前線程中處理operation完成后的結(jié)果,可以使用NSOperation的waitUntilFinished方法阻塞當前線程剿骨,等待operation完成。通常我們應該避免編寫這樣的代碼,阻塞當前線程可能是一種簡便的解決方案,但是它引入了更多的串行代碼,限制了整個應用的并發(fā)性,同時也降低了用戶體驗埠褪。絕對不要在應用主線程中等待一個Operation,只能在第二或次要線程中等待浓利。阻塞主線程將導致應用無法響應用戶事件,應用也將表現(xiàn)為無響應。
// 會阻塞當前線程钞速,等到某個operation執(zhí)行完畢
[operation waitUntilFinished];
除了等待單個Operation完成,你也可以同時等待一個queue中的所有操作,使用NSOperationQueue的waitUntilAllOperationsAreFinished方法贷掖。注意:在等待一個 queue時,應用的其它線程仍然可以往queue中添加Operation,因此可能會加長線程的等待時間。
// 阻塞當前線程渴语,等待queue的所有操作執(zhí)行完畢
[queue waitUntilAllOperationsAreFinished];
注意:waitUntilAllOperationsAreFinished一定要在操作隊列添加了操作后再設置苹威。即,先向operation queue中添加operation驾凶,再調(diào)用[operationQueue waitUntilAllOperationsAreFinished]牙甫。
NSBlockOperation *blkop = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"執(zhí)行操作 %@",[NSThread currentThread]);
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:blkop];
// waitUntilAllOperationsAreFinished就像GCD的barrier一樣起到隔離作用
// waitUntilAllOperationsAreFinished必須要在操作添加到隊列后設置
// waitUntilAllOperationsAreFinished必須要在NSLog(@"finish");之前設置waitUntilAllOperationsAreFinished
[queue waitUntilAllOperationsAreFinished];
NSLog(@"finish");
8、有了GCD调违,為什么還有要用NSOperationQueue
- GCD是底層的C語言構(gòu)成的API窟哺,而NSOperationQueue以及相關對象是基于GCD的Objective-C對象的封裝,作為一個對象技肩,NSOperationQueue為我們提供了更多的選擇
- NSOperationQueue任務可以很方便的取消(也只能取消未執(zhí)行的任務)混巧,而GCD沒法停止已經(jīng)加入隊列的任務(其實是有的叙赚,但需要許多復雜的代碼)
- 不像GCD那樣的是按FIFO順序來執(zhí)行的妄荔,NSOperation能夠方便地通過依賴關系設置操作執(zhí)行順序烘挫,可以控制任務在特定的任務執(zhí)行完后才執(zhí)行;而GCD要實現(xiàn)這個功能的話雳锋,就需要通過barrier或者group來控制執(zhí)行順序黄绩,如果依賴關系復雜的話,代碼邏輯就非常復雜了
- NSOperation支持KVO(Key-Value Observing)玷过,可以方便的監(jiān)聽任務的狀態(tài)(完成爽丹、執(zhí)行中筑煮、取消等等狀態(tài))
- NSOperation可以設置同一個隊列中任務的優(yōu)先級,能夠使同一個并行隊列中的任務區(qū)分先后地執(zhí)行粤蝎,而在GCD中真仲,我們只能區(qū)分不同任務隊列的優(yōu)先級,如果要區(qū)分block任務的優(yōu)先級初澎,也需要大量的復雜代碼
- 還可以通過自定義NSOperation秸应,封裝任務邏輯,提高整個代碼的復用度
- 綜合比較其各自使用范圍如下
- GCD更接近底層碑宴,而NSOperationQueue則更高級抽象软啼,所以GCD在追求性能的底層操作來說,是速度最快的延柠。
- 從異步操作之間的事務性祸挪,順序行,依賴關系贞间。GCD需要自己寫更多的代碼來實現(xiàn)贿条,而NSOperationQueue已經(jīng)內(nèi)建了這些支持
- 如果異步操作的過程需要更多的被交互和UI呈現(xiàn)出來,NSOperationQueue會是一個更好的選擇增热。底層代碼中整以,任務之間不太互相依賴,而需要更高的并發(fā)能力峻仇,GCD則更有優(yōu)勢
9公黑、小結(jié)
雖然在iOS開發(fā)中,多線程方法大部分使用的還是GCD础浮,但是對于某些特殊需求,如取消任務奠骄、設置任務執(zhí)行順序豆同、任務狀態(tài)監(jiān)聽、復雜任務封裝等還是推薦使用NSOperationQueue含鳞,實現(xiàn)起來會方便很多影锈。
至此,iOS中常用的多線程方式介紹完畢蝉绷。