天天看點

IOS多線程學習七:NSOperation1.簡介2.操作和操作隊列3.使用步驟4.基本使用5.控制串行并發6.操作依賴7.NSOperation優先級8.線程間通信9.其他10常用屬性和方法歸納

文章目錄

  • 1.簡介
  • 2.操作和操作隊列
  • 3.使用步驟
  • 4.基本使用
    • 4.1建立操作
      • 4.1.1 NSInvocationOperation
      • 4.1.2 NSBlockOperation
      • 4.1.3 自定義繼承自NSOperation的子類
    • 4.2建立隊列
      • 主隊列
      • 自定義隊列(非主隊列)
    • 4.3 将操作加入到隊列中
  • 5.控制串行并發
  • 6.操作依賴
  • 7.NSOperation優先級
  • 8.線程間通信
  • 9.其他
    • 9.1線程安全
      • NSLock
    • 9.2挂起
    • 9.3取消
  • 10常用屬性和方法歸納

參考博文: https://www.jianshu.com/p/4b1d77054b35

1.簡介

實際上NSOperation,NSOperationQueue是基于GCD更高一層的封裝,完全面向對象。但是比GCD更簡單易用,代碼可讀性也更高。

為什麼要使用NSOperation,NSOperationQueue?

1.可添加完成的代碼塊,在操作完成後執行。

2.添加操作之前的依賴關系,友善的控制執行順序。

3.設定操作執行的優先級

4.可以很友善的取消一個操作的執行。

5.使用KVO觀察對操作執行狀态的更改:isExecuting,isFinished,iscancel

2.操作和操作隊列

NSOperation,NSOperationQueue中也有類似的任務(操作)和隊列(操作隊列)的概念。

  • 操作(Operation):

    操作的意思就是你線上程中執行的那段代碼。

    在GCD中是放在block中的。在NSOperation中,我們使用NSOperation子類NSInvocationOperation,NSBlockOperation,或者自定義子類來封裝操作。

  • 操作隊列

    存放操作的隊列。不同于GCD中的排程隊列FIFO(先進先出)的原則。NSOperationQueue對于添加到隊列中的操作,首先進入準備就緒的狀态(取決于操作之間的依賴關系),然後進入就緒狀态(操作的開始執行順序,而非結束執行順序,由操作間先對的優先級決定)。

  • 隊列通過設定最大并發操作數(maxConcurrentOperation)來控制并發,串行。
  • NSOperationQueue提供兩種不同類型的隊列:主隊列和自定義隊列。主隊列運作在主線程之上,而自定義隊列在背景執行。

3.使用步驟

NSOperation需要配合NSOperationQueue來實作多線程。因為預設情況下,NSOperation單獨使用時系統同步執行操作,配合NSOperationQueue我們能更好的實作異步操作。

NSOperation實作多線程的使用步驟分為三步:

1.建立操作:先将需要執行的操作封裝到一個NSOperation對象中。

2.建立隊列:建立NSOperationQueue對象

3.将操作加入到隊列中:将NSOperation對象添加到NSOperationQueue對象中

之後,系統會自動将NSOpperationQueue中的NSOperation取出來,在新線程中執行操作。

4.基本使用

4.1建立操作

NSOperation 是個抽象類,不能用來封裝操作。我們隻有使用它的子類來封裝操作。有三種方式:

1.使用子類NSInvocationOperation

2.使用子類NSBlockOperation

3.自定義繼承自NSOperation的子類,通過實作内部相應的方法來封裝操作。

如果沒有加入隊列中,需要調用[op start]啟用操作。

在不使用NSOperationQueue,單獨使用NSOperation的情況下系統同步執行操作。

4.1.1 NSInvocationOperation

/**
 * 使用子類 NSInvocationOperation
 */
- (void)useInvocationOperation {

    // 1.建立 NSInvocationOperation 對象
    NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];

    // 2.調用 start 方法開始執行操作
    [op start];
}

/**
 * 任務1
 */
- (void)task1 {
    for (int i = 0; i < 2; i++) {
        [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
        NSLog(@"1---%@", [NSThread currentThread]); // 列印目前線程
    }
}
           

輸出結果:

IOS多線程學習七:NSOperation1.簡介2.操作和操作隊列3.使用步驟4.基本使用5.控制串行并發6.操作依賴7.NSOperation優先級8.線程間通信9.其他10常用屬性和方法歸納

可以看到:操作是在目前線程執行的,并沒有開啟新線程。

如果在其他線程中執行操作,則列印結果為其他線程。

// 在其他線程使用子類 NSInvocationOperation
[NSThread detachNewThreadSelector:@selector(useInvocationOperation) toTarget:self withObject:nil];
           

輸出結果:

IOS多線程學習七:NSOperation1.簡介2.操作和操作隊列3.使用步驟4.基本使用5.控制串行并發6.操作依賴7.NSOperation優先級8.線程間通信9.其他10常用屬性和方法歸納

可以看到:在其他線程中單獨使用子類NSInvocationOperation,操作是在目前調用它的其他線程執行的,并沒有開啟新線程。

4.1.2 NSBlockOperation

/**
 * 使用子類 NSBlockOperation
 */
 * (void)useBlockOperation {

    // 1.建立 NSBlockOperation 對象
    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"1---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];

    // 2.調用 start 方法開始執行操作
    [op start];
}
           

輸出結果:

IOS多線程學習七:NSOperation1.簡介2.操作和操作隊列3.使用步驟4.基本使用5.控制串行并發6.操作依賴7.NSOperation優先級8.線程間通信9.其他10常用屬性和方法歸納
  • 可以看到:在沒有使用NSOperationQueue,沒有開啟新線程。

    NSBlockOperation還提供了一個方法addExecutionBlock,為NSBlockOperation添加額外的操作。隻要NSBlockOperation封裝的操作數大于1,就會開啟新線程,異步執行。

/**
 * 使用子類 NSBlockOperation
 * 調用方法 AddExecutionBlock:
 */
- (void)useBlockOperationAddExecutionBlock {

    // 1.建立 NSBlockOperation 對象
    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"1---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];

    // 2.添加額外的操作
    [op addExecutionBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"2---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
    [op addExecutionBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"3---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
    [op addExecutionBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"4---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
    [op addExecutionBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"5---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
    [op addExecutionBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"6---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
    [op addExecutionBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"7---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
    [op addExecutionBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"8---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];

    // 3.調用 start 方法開始執行操作
    [op start];
}
           

輸出結果:

IOS多線程學習七:NSOperation1.簡介2.操作和操作隊列3.使用步驟4.基本使用5.控制串行并發6.操作依賴7.NSOperation優先級8.線程間通信9.其他10常用屬性和方法歸納

4.1.3 自定義繼承自NSOperation的子類

如果使用子類NSInvocationOperation,NSBlockOperation不能滿足日常需求

( 什麼情況下不能滿足日常需求?)

我們可以使用自定義自NSOperation的子類。可以通過重寫main或者start方法來定義自己的NSOperation對象。重寫main方法比較簡單,我們不需要管理操作的狀态屬性isExecuting和isFinished.當main方法執行完傳回時,這個操作就結束了。

// YSCOperation.h 檔案
#import <Foundation/Foundation.h>

@interface YSCOperation : NSOperation

@end

// YSCOperation.m 檔案
#import "YSCOperation.h"

@implementation YSCOperation

- (void)main {
    if (!self.isCancelled) {
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"1---%@", [NSThread currentThread]);
        }
    }
}

@end
           

然後在使用的時候導入頭檔案YSCOperation.h

/**
 * 使用自定義繼承自 NSOperation 的子類
 */
- (void)useCustomOperation {
    // 1.建立 YSCOperation 對象
    YSCOperation *op = [[YSCOperation alloc] init];
    // 2.調用 start 方法開始執行操作
    [op start];
}
           

輸出結果:

IOS多線程學習七:NSOperation1.簡介2.操作和操作隊列3.使用步驟4.基本使用5.控制串行并發6.操作依賴7.NSOperation優先級8.線程間通信9.其他10常用屬性和方法歸納

沒有開啟新線程。

4.2建立隊列

NSOperationQueue一共有兩種隊列:主隊列,自定義隊列。其中自定義隊列同時包含串行,并行功能。

主隊列

凡是添加到主隊列中的操作,都會放到主線程中執行。

不包括addExecutionBlock添加的額外操作,額外操作可能在其他線程執行)

// 主隊列擷取方法
NSOperationQueue *queue = [NSOperationQueue mainQueue];
           

自定義隊列(非主隊列)

添加到這種隊列中的操作,就會自動放到子線程中執行。

// 自定義隊列建立方法
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
           

4.3 将操作加入到隊列中

NSOperation需要配合NSOperationQueue來實作多線程。

操作加入隊列有2種方法:

1.-(void)addOperation:(NSoperation*)op;

/**
 * 使用 addOperation: 将操作加入到操作隊列中
 */
- (void)addOperationToQueue {

    // 1.建立隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    // 2.建立操作
    // 使用 NSInvocationOperation 建立操作1
    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];

    // 使用 NSInvocationOperation 建立操作2
    NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task2) object:nil];

    // 使用 NSBlockOperation 建立操作3
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"3---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
    [op3 addExecutionBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"4---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];

    // 3.使用 addOperation: 添加所有操作到隊列中
    [queue addOperation:op1]; // [op1 start]
    [queue addOperation:op2]; // [op2 start]
    [queue addOperation:op3]; // [op3 start]
}
           

結果:加入隊列後會自動調[op start],并能開啟新線程,進行并發執行。

IOS多線程學習七:NSOperation1.簡介2.操作和操作隊列3.使用步驟4.基本使用5.控制串行并發6.操作依賴7.NSOperation優先級8.線程間通信9.其他10常用屬性和方法歸納

2.-(void)addOperationWithBlock:(void(^)(void))block;

無需先建立操作,在block中添加操作,直接将包含操作的block加入隊列中。

/**
 * 使用 addOperationWithBlock: 将操作加入到操作隊列中
 */

 * (void)addOperationWithBlockToQueue {
    // 1.建立隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    // 2.使用 addOperationWithBlock: 添加操作到隊列中
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"1---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"2---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"3---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
}
           

結果:

IOS多線程學習七:NSOperation1.簡介2.操作和操作隊列3.使用步驟4.基本使用5.控制串行并發6.操作依賴7.NSOperation優先級8.線程間通信9.其他10常用屬性和方法歸納

5.控制串行并發

最大并發操作數,maxConcurrentOperationCount,用來控制一個隊列中可以有多少個操作同時參與并發執行。

  • 預設為-1,表示不進行限制,可進行并發執行。
  • 為1時,隊列為串行隊列。隻能串行執行。
  • 大于1時,隊列為并發隊列。操作并發執行,這個值不應超過系統限制。即使自己設定一個很大的值,系統也會自動調整為min{自己設定的值,系統設定的預設最大值}
/**
 * 設定 MaxConcurrentOperationCount(最大并發操作數)
 */
- (void)setMaxConcurrentOperationCount {

    // 1.建立隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    // 2.設定最大并發操作數
    queue.maxConcurrentOperationCount = 1; // 串行隊列
// queue.maxConcurrentOperationCount = 2; // 并發隊列
// queue.maxConcurrentOperationCount = 8; // 并發隊列

    // 3.添加操作
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"1---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"2---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"3---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"4---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
}
           
  • 并發操作數為1,串行隊列,任務逐個執行
    IOS多線程學習七:NSOperation1.簡介2.操作和操作隊列3.使用步驟4.基本使用5.控制串行并發6.操作依賴7.NSOperation優先級8.線程間通信9.其他10常用屬性和方法歸納
  • 操作數為2,有2個操作可以參與并發執行。前兩個操作完成後,繼續2個操作并發執行。
    IOS多線程學習七:NSOperation1.簡介2.操作和操作隊列3.使用步驟4.基本使用5.控制串行并發6.操作依賴7.NSOperation優先級8.線程間通信9.其他10常用屬性和方法歸納

6.操作依賴

控制操作之間執行的先後順序。 [op2 addDependency:op1];前者依賴于後者,後者先執行,再執行前者。

/**
 * 操作依賴
 * 使用方法:addDependency:
 */
- (void)addDependency {

    // 1.建立隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    // 2.建立操作
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"1---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"2---%@", [NSThread currentThread]); // 列印目前線程
        }
    }];

    // 3.添加依賴
    [op2 addDependency:op1]; // 讓op2 依賴于 op1,則先執行op1,在執行op2

    // 4.添加操作到隊列中
    [queue addOperation:op1];
    [queue addOperation:op2];
}
           
IOS多線程學習七:NSOperation1.簡介2.操作和操作隊列3.使用步驟4.基本使用5.控制串行并發6.操作依賴7.NSOperation優先級8.線程間通信9.其他10常用屬性和方法歸納

7.NSOperation優先級

// 優先級的取值
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
    NSOperationQueuePriorityVeryLow = -8L,
    NSOperationQueuePriorityLow = -4L,
    NSOperationQueuePriorityNormal = 0,
    NSOperationQueuePriorityHigh = 4,
    NSOperationQueuePriorityVeryHigh = 8
};
           

對于添加到隊列中的操作,首先進入準備就緒的狀态(就緒狀态取決于操作之間的依賴關系),然後進入就緒狀态的操作的開始執行順序(非結束執行順序)由操作之間相對的優先級決定(優先級是操作對象自身的屬性)。優先級不能取代依賴關系,如果要控制操作間的啟動順序,必須使用依賴關系。

8.線程間通信

當在子線程完成了耗時操作時,需要回到主線程,那麼就用到了線程間的通信。

/**
 * 線程間通信
 */
- (void)communication {

    // 1.建立隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    // 2.添加操作
    [queue addOperationWithBlock:^{
        // 異步進行耗時操作
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
            NSLog(@"1---%@", [NSThread currentThread]); // 列印目前線程
        }

        // 回到主線程
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            // 進行一些 UI 重新整理等操作
            for (int i = 0; i < 2; i++) {
                [NSThread sleepForTimeInterval:2]; // 模拟耗時操作
                NSLog(@"2---%@", [NSThread currentThread]); // 列印目前線程
            }
        }];
    }];
}
           
IOS多線程學習七:NSOperation1.簡介2.操作和操作隊列3.使用步驟4.基本使用5.控制串行并發6.操作依賴7.NSOperation優先級8.線程間通信9.其他10常用屬性和方法歸納

9.其他

9.1線程安全

給線程加鎖,當一個線程執行該操作時,不允許其他線程進行操作。

ios實作線程加鎖的方式:@synchronized、 NSLock、NSRecursiveLock、NSCondition、NSConditionLock、pthread_mutex、dispatch_semaphore、OSSpinLock、atomic(property) set/ge等等各種方式。

NSLock

進入鎖時用 NSLock對象調用lock方法,解鎖時調用unlock方法。

/**
 * 線程安全:使用 NSLock 加鎖
 * 初始化火車票數量、賣票視窗(線程安全)、并開始賣票
 */

- (void)initTicketStatusSave {
    NSLog(@"currentThread---%@",[NSThread currentThread]); // 列印目前線程

    self.ticketSurplusCount = 50;

    self.lock = [[NSLock alloc] init];  // 初始化 NSLock 對象

    // 1.建立 queue1,queue1 代表北京火車票售賣視窗
    NSOperationQueue *queue1 = [[NSOperationQueue alloc] init];
    queue1.maxConcurrentOperationCount = 1;

    // 2.建立 queue2,queue2 代表上海火車票售賣視窗
    NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
    queue2.maxConcurrentOperationCount = 1;

    // 3.建立賣票操作 op1
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        [self saleTicketSafe];
    }];

    // 4.建立賣票操作 op2
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        [self saleTicketSafe];
    }];

    // 5.添加操作,開始賣票
    [queue1 addOperation:op1];
    [queue2 addOperation:op2];
}

/**
 * 售賣火車票(線程安全)
 */
- (void)saleTicketSafe {
    while (1) {

        // 加鎖
        [self.lock lock];

        if (self.ticketSurplusCount > 0) {
            //如果還有票,繼續售賣
            self.ticketSurplusCount--;
            NSLog(@"%@", [NSString stringWithFormat:@"剩餘票數:%d 視窗:%@", self.ticketSurplusCount, [NSThread currentThread]]);
            [NSThread sleepForTimeInterval:0.2];
        }

        // 解鎖
        [self.lock unlock];

        if (self.ticketSurplusCount <= 0) {
            NSLog(@"所有火車票均已售完");
            break;
        }
    }
}
           

9.2挂起

暫停隊列裡任務的執行,可以将隊列挂起,當任務處于執行狀态,設定隊列挂起不會影響其執行,受影響的是那些還沒有執行的任務。隊列挂起後,可以修改其狀态再次恢複任務。

if(self.queue.suspended){
    self.queue.suspended=NO;
}else{
   self.queue.suspended=YES;
}
           

9.3取消

已經在執行的任務不會受影響,還沒有執行的任務就不會再執行了。

[self.queue cancelAllOperations];
           

在自定義的子類裡取消操作,需要在main函數裡,執行完一個耗時操作後,需要加一個是否取消任務的判斷,再去執行另一個耗時操作,添加判斷:

if(self.cancelled){

return;

}

10常用屬性和方法歸納

10.1 NSOperation常用屬性和方法

取消操作方法

  • (void)cancel; 可取消操作,實質是标記 isCancelled 狀态。

判斷操作狀态方法

  • (BOOL)isFinished; 判斷操作是否已經結束。
  • (BOOL)isCancelled; 判斷操作是否已經标記為取消。
  • (BOOL)isExecuting; 判斷操作是否正在在運作。
  • (BOOL)isReady; 判斷操作是否處于準備就緒狀态,這個值和操作的依賴關系相關。

操作同步

  • (void)waitUntilFinished; 阻塞目前線程,直到該操作結束。可用于線程執行順序的同步。
  • (void)setCompletionBlock:(void (^)(void))block; completionBlock 會在目前操作執行完畢時執行 completionBlock。
  • (void)addDependency:(NSOperation *)op; 添加依賴,使目前操作依賴于操作 op 的完成。
  • (void)removeDependency:(NSOperation *)op; 移除依賴,取消目前操作對操作 op 的依賴。

@property (readonly, copy) NSArray<NSOperation *> *dependencies; 在目前操作開始執行之前完成執行的所有操作對象數組。

10.2 NSOperationQueue 常用屬性和方法

取消/暫停/恢複操作

  • (void)cancelAllOperations; 可以取消隊列的所有操作。
  • (BOOL)isSuspended; 判斷隊列是否處于暫停狀态。 YES 為暫停狀态,NO 為恢複狀态。
  • (void)setSuspended:(BOOL)b; 可設定操作的暫停和恢複,YES 代表暫停隊列,NO 代表恢複隊列。

操作同步

  • (void)waitUntilAllOperationsAreFinished; 阻塞目前線程,直到隊列中的操作全部執行完畢。

    添加/擷取操作

  • (void)addOperationWithBlock:(void (^)(void))block; 向隊列中添加一個 NSBlockOperation 類型操作對象。
  • (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait; 向隊列中添加操作數組,wait 标志是否阻塞目前線程直到所有操作結束
  • (NSArray *)operations; 目前在隊列中的操作數組(某個操作執行結束後會自動從這個數組清除)。
  • (NSUInteger)operationCount; 目前隊列中的操作數。

    擷取隊列

  • (id)currentQueue; 擷取目前隊列,如果目前線程不是在 NSOperationQueue 上運作則傳回 nil。
  • (id)mainQueue; 擷取主隊列。

    注意:

這裡的暫停和取消(包括操作的取消和隊列的取消)并不代表可以将目前的操作立即取消,而是當目前的操作執行完畢之後不再執行新的操作。

暫停和取消的差別就在于:暫停操作之後還可以恢複操作,繼續向下執行;而取消操作之後,所有的操作就清空了,無法再接着執行剩下的操作。