iOS開發之NSOperation & NSOperationQueue

1、簡介編程

(1) NSOperationQueue(操做隊列)是由GCD提供的隊列模型的Cocoa抽象,是一套Objective-C的API,爲了使併發(多線程)編程變得更加簡單,但效率比GCD略低。在實際開發中NSOperationQueue是首選。安全

(2) GCD提供了更加底層的控制,而操做隊列則在GCD之上實現了一些方便的功能,這些功能對於開發者而言一般是最好最安全的選擇。網絡

隊列及操做多線程

(1)NSOperationQueue有兩種不一樣類型的隊列:主隊列和自定義隊列併發

(2)主隊列運行在主線程上。異步

(3)自定義隊列在後臺執行(只要自定義隊列,都是併發的)。atom

(4) NSOperation是不能直接使用的,隊列處理的任務是NSOperation的子類:線程

(a)NSInvocationOperation隊列

(b)NSBlockOperation圖片

2NSOperation的基本使用步驟

基本使用步驟

(1) 定義操做隊列

(2) 定義操做

(3) 將操做添加到隊列

提示:一旦將操做添加到隊列,操做就會當即被調度執行

3NSInvocationOperation(調度操做)

定義隊列:

self.myQueue = [[NSOperationQueue alloc] init];

操做調用的方法:

- (void)operationAction:(id)obj

{

    NSLog(@"%@ - obj : %@", [NSThread currentThread], obj);

}

定義操做並添加到隊列:

NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction:) object:@(i)];

[self.myQueue addOperation:op];

例如:

其中myQueue 爲:

@property (nonatomic, strong) NSOperationQueue *myQueue;

- (void)demoOp2

{

    // 須要定義一個方法,可以接收一個參數

    // 是用起來不夠靈活

    NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demoOp:) object:@"hello op"];

   

// [self.myQueue addOperation:op];//在子線程運行

   

    [[NSOperationQueue mainQueue] addOperation:op];//在主線程運行

}

4NSBlockOperation(塊操做)

定義操做並添加到隊列

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{

    [self operationAction:@"Block Operation"];

}];

將操做添加到隊列

[self.myQueue addOperation:op];

【備註】NSBlockOperation比NSInvocationOperation更加靈活

例如:

其中myQueue 爲:

@property (nonatomic, strong) NSOperationQueue *myQueue;

#pragma mark 設置任務的執行順序

- (void)demoOp3

{

NSBlockOperation *op1 =

[NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"下載圖片 %@", [NSThread currentThread]);

}];

 

NSBlockOperation *op2 =

[NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"修飾圖片 %@", [NSThread currentThread]);

    }];

NSBlockOperation *op3 =

[NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"保存圖片 %@", [NSThread currentThread]);

}];

 

NSBlockOperation *op4 =

[NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"更新UI %@", [NSThread currentThread]);

    }];

   

    // 設定執行順序, Dependency依賴,系統可能會開多個線程,但不會太多

    // 依賴關係是能夠跨隊列的!

    [op2 addDependency:op1];

    [op3 addDependency:op2];

    [op4 addDependency:op3];

    // GCD是串行隊列,異步任務,只會開一個線程

   

    [self.myQueue addOperation:op1];

    [self.myQueue addOperation:op2];

    [self.myQueue addOperation:op3];

    // 全部UI的更新須要在主線程上進行,使op4在主線程執行

    [[NSOperationQueue mainQueue] addOperation:op4];

}

 

 

5、設置操做的依賴關係

NSBlockOperation *op1 =

[NSBlockOperation blockOperationWithBlock:^{

    NSLog(@"%@ - 下載圖片", [NSThread currentThread]);

}];

 

NSBlockOperation *op2 =

[NSBlockOperation blockOperationWithBlock:^{

    NSLog(@"%@ - 添加圖片濾鏡", [NSThread currentThread]);

}];

 

NSBlockOperation *op3 =

[NSBlockOperation blockOperationWithBlock:^{

    NSLog(@"%@ - 更新UI", [NSThread currentThread]);

}];

 

// [op1 addDependency:op3];會形成循環依賴

[op2 addDependency:op1];

[op3 addDependency:op2];

[self.myQueue addOperation:op1];

[self.myQueue addOperation:op2];

[[NSOperationQueue mainQueue] addOperation:op3];

提示:利用addDependency能夠指定操做之間的彼此依賴關係(執行前後順序)

注意:不要出現循環依賴!

6、設置同時併發的線程數量

//設置同時併發的線程數量可以有效地下降CPU和內存的開銷,這一功能用GCD不容易實現。

// 新建線程是有開銷的

// 在設定同時併發的最大線程數時,若是前一個線程工做完成,可是尚未銷燬,會新建線程

// 應用場景:網絡開發中,下載工做!(線程開銷:CPU,MEM)電量!

// 若是是3G,開3個子線程

// 若是是WIFI,開6個子線程

[self.myQueue setMaxConcurrentOperationCount:2];

for (int i = 0; i < 10; ++i) {

    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{

        [self operationAction:@(i)];

    }];

    [self.myQueue addOperation:op];

}

相關文章
相關標籤/搜索