NSInvocationOperation

The NSInvocationOperationclass is a concrete subclass of NSOperationthat you use to initiate an operation that consists of invoking a selector on a specified object. This class implements a non-concurrent operation.
根據蘋果官方的解釋說,NSInvocationOperationNSOperation一個子類,你可以初始化一個操作,該操作在一個指定的物件上去呼叫一個selector,並且NSOperation這個類實現了一個非併發的操作。具體怎麼使用NSInvocationOperation這個類呢?

NSInvocationOperation的建立

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationTest) object:nil];

NSInvocationOperation建立完成之後,怎麼觸發該執行緒的執行?一共有兩種方式執行該執行緒
方式一:

//呼叫start方法執行,此執行方式在主執行緒中執行,沒有開闢新的執行緒
// ThreadDemo[20397:12090175] ------------<NSThread: 0x60400007da00>{number = 1, name = main}-----
[operation start];

呼叫start方法執行此執行緒,但是使用此方法,並不會開闢新的執行緒來執行程式碼
方式二:

    //加入到佇列中去執行,此種方式會開闢執行緒,在新的執行緒中執行程式碼
// ThreadDemo[20432:12091400] ------------<NSThread: 0x600000273240>{number = 3, name = (null)}-----
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];

根據列印資訊可以看出,把建立的NSInvocationOperation加入到一個queue佇列中去執行,會開闢新的執行緒執行任務。

NSBlockOperation

The NSBlockOperationclass is a concrete subclass of NSOperationthat manages the concurrent execution of one or more blocks. You can use this object to execute several blocks at once without having to create separate operation objects for each. When executing more than one block, the operation itself is considered finished only when all blocks have finished executing.
NSBlockOperation類是NSOperation的一個具體子類,它管理一個或多個塊的併發執行。您可以使用這個物件一次執行幾個塊,而不必為每個塊建立單獨的操作物件。當執行多個塊時,只有當所有塊都完成執行時,才考慮操作本身。

NSBlockOperation的建立

 //建立NSBlockOperation執行緒方式1
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"------operation------%@-----", [NSThread currentThread]);
}];
[operation start];
//建立NSBlockOperation執行緒方式2
NSBlockOperation *operation1 = [[NSBlockOperation alloc] init];
[operation1 addExecutionBlock:^{
NSLog(@"------operation1------%@-----", [NSThread currentThread]);
}];
[operation1 start];

這樣建立後呼叫start方法,同樣在主執行緒中執行,下面看看把NSBlockOperation新增到queue佇列中去執行

    NSBlockOperation *operation = [[NSBlockOperation alloc] init];
[operation addExecutionBlock:^{
NSLog(@"------block1------%@-----", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"------block2------%@-----", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"------block3------%@-----", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"------block4------%@-----", [NSThread currentThread]);
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];

可以看出,加入到queue佇列中的任務全都是非同步執行

使用NSOperationQueue來建立任務

/**
使用queue佇列來自己新增任務並執行
*/
- (void)testOperationQueue {
//建立queue佇列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//新增任務
[queue addOperationWithBlock:^{
NSLog(@"------block1------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block2------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block3------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block4------%@-----", [NSThread currentThread]);
}];
}

可以看出,使用queue佇列來建立任務,省去了建立NSInvocationOperationNSBlockOperation再加入到佇列中執行。
上面列出了三種實現NSOperation建立多執行緒的方式,在具體的工作中,使用哪種方式還是要根據工作需要具體對待。

佇列的使用----依賴執行任務

有這個一個場景:任務3的執行依賴於任務2,任務2的執行依賴於任務1,相當於一個序列佇列,只有當前面一個執行完成之後才開始下一個任務的執行,下面看看具體的實現方式:

/**
使用場景一:任務的依賴執行
*/
- (void)testDepenceyOperation {
//建立要執行的任務
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"------operation1------%@-----", [NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"------operation2------%@-----", [NSThread currentThread]);
}];
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"------operation3------%@-----", [NSThread currentThread]);
}];
//給任務新增依賴,任務3依賴任務2,任務2依賴任務1
[operation3 addDependency:operation2];
[operation2 addDependency:operation1]; NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
}

佇列的使用---設定最大併發數

設定最大併發數量,為了保證app的整個生命週期不會佔用過多的資源,在有大量併發執行緒執行的時候,一定要進行設定,不然可能會造成app閃退。

- (void)testMacConcurrentOperationCount {
//建立queue佇列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//設定執行緒的最大併發數量
queue.maxConcurrentOperationCount = 3;
//新增任務
[queue addOperationWithBlock:^{
NSLog(@"------block1------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block2------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block3------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block4------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block5------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block6------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block7------%@-----", [NSThread currentThread]);
}];
}