NSOperation詳盡總結(jié)

一格郁、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
自定義NSOperation

3.隊列 - 默認是并發(fā)的.
@interface NSOperationQueue : NSObject

4.總結(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)建好的任務加入到隊列中去钥星。總共有兩種方法

  1. - (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í)行。

  1. - (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
  1. maxConcurrentOperationCount默認情況下為-1,表示不進行限制,默認為并發(fā)執(zhí)行窃肠。
  2. maxConcurrentOperationCount為1時搀菩,進行串行執(zhí)行州既。
  3. 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

解析:

  1. 上面創(chuàng)建了兩個blockOperation并且分別設置了優(yōu)先級祖灰。顯然blkop1的優(yōu)先級低于blkop2的優(yōu)先級钟沛。然后調(diào)用了隊列的addOperation:方法使操作入隊。最后輸出結(jié)果證明局扶,操作在對列中的順序取決于addOperation:方法而不是優(yōu)先級恨统。
  2. 雖然blkop2優(yōu)先級高于blkop1,但是bloop1卻先于blkop2執(zhí)行完成三妈。所以畜埋,優(yōu)先級高的操作不一定先執(zhí)行完成。
  3. 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秸应,封裝任務邏輯,提高整個代碼的復用度
  • 綜合比較其各自使用范圍如下
  1. GCD更接近底層碑宴,而NSOperationQueue則更高級抽象软啼,所以GCD在追求性能的底層操作來說,是速度最快的延柠。
  2. 從異步操作之間的事務性祸挪,順序行,依賴關系贞间。GCD需要自己寫更多的代碼來實現(xiàn)贿条,而NSOperationQueue已經(jīng)內(nèi)建了這些支持
  3. 如果異步操作的過程需要更多的被交互和UI呈現(xiàn)出來,NSOperationQueue會是一個更好的選擇增热。底層代碼中整以,任務之間不太互相依賴,而需要更高的并發(fā)能力峻仇,GCD則更有優(yōu)勢

9公黑、小結(jié)

雖然在iOS開發(fā)中,多線程方法大部分使用的還是GCD础浮,但是對于某些特殊需求,如取消任務奠骄、設置任務執(zhí)行順序豆同、任務狀態(tài)監(jiān)聽、復雜任務封裝等還是推薦使用NSOperationQueue含鳞,實現(xiàn)起來會方便很多影锈。
至此,iOS中常用的多線程方式介紹完畢蝉绷。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸭廷,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子熔吗,更是在濱河造成了極大的恐慌辆床,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桅狠,死亡現(xiàn)場離奇詭異讼载,居然都是意外死亡轿秧,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門咨堤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來菇篡,“玉大人,你說我怎么就攤上這事一喘∏梗” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵凸克,是天一觀的道長议蟆。 經(jīng)常有香客問我,道長触徐,這世上最難降的妖魔是什么咪鲜? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮撞鹉,結(jié)果婚禮上疟丙,老公的妹妹穿的比我還像新娘。我一直安慰自己鸟雏,他們只是感情好享郊,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著孝鹊,像睡著了一般炊琉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上又活,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天苔咪,我揣著相機與錄音,去河邊找鬼柳骄。 笑死团赏,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的耐薯。 我是一名探鬼主播舔清,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼曲初!你這毒婦竟也來了体谒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤臼婆,失蹤者是張志新(化名)和其女友劉穎抒痒,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體颁褂,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡评汰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年纷捞,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片被去。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡主儡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出惨缆,到底是詐尸還是另有隱情糜值,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布坯墨,位于F島的核電站寂汇,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏捣染。R本人自食惡果不足惜骄瓣,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望耍攘。 院中可真熱鬧榕栏,春花似錦、人聲如沸蕾各。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽式曲。三九已至妨托,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吝羞,已是汗流浹背兰伤。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留钧排,地道東北人敦腔。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像卖氨,于是被迫代替她去往敵國和親会烙。 傳聞我的和親對象是個殘疾皇子负懦,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容