NSOperation
1、NSOperation
1.簡介
NSOperation實例封裝了須要履行的操作和履行操作所需的數據,而且可以或許以並發或非並發的方法履行這個操作。
NSOperation自己是籠統基類,是以必需應用它的子類,應用NSOperation子類的方法有2種:
1> Foundation框架供給了兩個詳細子類直接供我們應用:NSInvocationOperation和NSBlockOperation
2> 自界說子類繼續NSOperation,完成外部響應的辦法
2.履行操作
NSOperation挪用start辦法便可開端履行操作,NSOperation對象默許按同步方法履行,也就是在挪用start辦法的誰人線程中直接履行。NSOperation對象的isConcurrent辦法會告知我們這個操作絕對於挪用start辦法的線程,是同步照樣異步履行。isConcurrent辦法默許前往NO,表現操作與挪用線程同步履行
3.撤消操作
operation開端履行以後, 默許會一向履行操作直到完成,我們也能夠挪用cancel辦法半途撤消操作
[operation cancel];
4.監聽操作的履行
假如我們想在一個NSOperation履行終了後做一些工作,就挪用NSOperation的setCompletionBlock辦法來設置想做的工作
operation.completionBlock = ^() {
NSLog(@"履行終了");
};
或許
[operation setCompletionBlock:^() {
NSLog(@"履行終了");
}];
2、NSInvocationOperation
1.簡介
基於一個對象和selector來創立操作。假如你曾經有現有的辦法來履行須要的義務,便可以應用這個類
2.創立並履行操作
// 這個操作是:挪用self的run辦法
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithtarget:self selector:@selector(run) object:nil];
// 開端履行義務(同步履行)
[operation start];
3、NSBlockOperation
1.簡介
可以或許並發地履行一個或多個block對象,一切相干的block都履行完以後,操作才算完成
2.創立並履行操作
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){
NSLog(@"履行了一個新的操作,線程:%@", [NSThread currentThread]);
}];
// 開端履行義務(這裡照樣同步履行)
[operation start];
3.經由過程addExecutionBlock辦法添加block操作
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){
NSLog(@"履行第1次操作,線程:%@", [NSThread currentThread]);
}];
[operation addExecutionBlock:^() {
NSLog(@"又履行了1個新的操作,線程:%@", [NSThread currentThread]);
}];
[operation addExecutionBlock:^() {
NSLog(@"又履行了1個新的操作,線程:%@", [NSThread currentThread]);
}];
[operation addExecutionBlock:^() {
NSLog(@"又履行了1個新的操作,線程:%@", [NSThread currentThread]);
}];
// 開端履行義務
[operation start];
打印信息以下:
2013-02-02 21:38:46.102 thread[4602:c07] 又履行了1個新的操作,線程:<NSThread: 0x7121d50>{name = (null), num = 1} 2013-02-02 21:38:46.102 thread[4602:3f03] 又履行了1個新的操作,線程:<NSThread: 0x742e1d0>{name = (null), num = 5} 2013-02-02 21:38:46.102 thread[4602:1b03] 履行第1次操作,線程:<NSThread: 0x742de50>{name = (null), num = 3} 2013-02-02 21:38:46.102 thread[4602:1303] 又履行了1個新的操作,線程:<NSThread: 0x7157bf0>{name = (null), num = 4}
可以看出,這4個block是並發履行的,也就是在分歧線程中履行的,num屬性可以算作是線程的id
4、自界說NSOperation
1.簡介
假如NSInvocationOperation和NSBlockOperation對象不克不及知足需求, 你可以直接繼續NSOperation, 並添加任何你想要的行動。繼續所需的任務量重要取決於你要完成非並發回是並發的NSOperation。界說非並發的NSOperation要簡略很多,只須要重載-(void)main這個辦法,在這個辦法外面履行主義務,並准確地呼應撤消事宜; 關於並發NSOperation, 你必需重寫NSOperation的多個根本辦法停止完成(這裡臨時先引見非並發的NSOperation)
2.非並發的NSOperation
好比叫做DownloadOperation,用來下載圖片
1> 繼續NSOperation,重寫main辦法,履行主義務
DownloadOperation.h
#import <Foundation/Foundation.h>
@protocol DownloadOperationDelegate;
@interface DownloadOperation : NSOperation
// 圖片的url途徑
@property (nonatomic, copy) NSString *imageUrl;
// 署理
@property (nonatomic, retain) id<DownloadOperationDelegate> delegate;
- (id)initWithUrl:(NSString *)url delegate:(id<DownloadOperationDelegate>)delegate;
@end
// 圖片下載的協定
@protocol DownloadOperationDelegate <NSObject>
- (void)downloadFinishWithImage:(UIImage *)image;
@end
DownloadOperation.m
#import "DownloadOperation.h"
@implementation DownloadOperation
@synthesize delegate = _delegate;
@synthesize imageUrl = _imageUrl;
// 初始化
- (id)initWithUrl:(NSString *)url delegate:(id<DownloadOperationDelegate>)delegate {
if (self = [super init]) {
self.imageUrl = url;
self.delegate = delegate;
}
return self;
}
// 釋放內存
- (void)dealloc {
[super dealloc];
[_delegate release];
[_imageUrl release];
}
// 履行主義務
- (void)main {
// 新建一個主動釋放池,假如是異步履行操作,那末將沒法拜訪到主線程的主動釋放池
@autoreleasepool {
// ....
}
}
@end
2> 准確呼應撤消事宜
operation開端履行以後,會一向履行義務直到完成,或許顯式地撤消操作。撤消能夠產生在任什麼時候候,乃至在operation履行之前。雖然NSOperation供給了一個辦法,讓運用撤消一個操作,然則辨認出撤消事宜則是我們本身的工作。假如operation直接終止, 能夠沒法收受接管一切已分派的內存或資本。是以operation對象須要檢測撤消事宜,並優雅地加入履行
NSOperation對象須要按期地挪用isCancelled辦法檢測操作能否曾經被撤消,假如前往YES(表現已撤消),則立刻加入履行。不論是自界說NSOperation子類,照樣應用體系供給的兩個詳細子類,都須要支撐撤消。isCancelled辦法自己異常輕量,可以頻仍地挪用而不發生年夜的機能喪失
以下處所能夠須要挪用isCancelled:
* 在履行任何現實的任務之前
* 在輪回的每次迭代進程中,假如每一個迭代絕對較長能夠須要挪用屢次
* 代碼中絕對比擬輕易中斷操作的任何處所
DownloadOperation的main辦法完成以下
- (void)main {
// 新建一個主動釋放池,假如是異步履行操作,那末將沒法拜訪到主線程的主動釋放池
@autoreleasepool {
if (self.isCancelled) return;
// 獲得圖片數據
NSURL *url = [NSURL URLWithString:self.imageUrl];
NSData *imageData = [NSData dataWithContentsOfURL:url];
if (self.isCancelled) {
url = nil;
imageData = nil;
return;
}
// 初始化圖片
UIImage *image = [UIImage imageWithData:imageData];
if (self.isCancelled) {
image = nil;
return;
}
if ([self.delegate respondsToSelector:@selector(downloadFinishWithImage:)]) {
// 把圖片數據傳回到主線程
[(NSObject *)self.delegate performSelectorOnMainThread:@selector(downloadFinishWithImage:) withObject:image waitUntilDone:NO];
}
}
}
NSOperationQueue
1、簡介
一個NSOperation對象可以經由過程挪用start辦法來履行義務,默許是同步履行的。也能夠將NSOperation添加到一個NSOperationQueue(操作隊列)中去履行,並且是異步履行的。
創立一個操作隊列:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
2、添加NSOperation到NSOperationQueue中
1.添加一個operation
[queue addOperation:operation];
2.添加一組operation
[queue addOperations:operations waitUntilFinished:NO];
3.添加一個block情勢的operation
[queue addOperationWithBlock:^() {
NSLog(@"履行一個新的操作,線程:%@", [NSThread currentThread]);
}];
NSOperation添加到queue以後,平日短時光內就會獲得運轉。然則假如存在依附,或許全部queue被暫停等緣由,也能夠須要期待。
留意:NSOperation添加到queue以後,相對不要再修正NSOperation對象的狀況。由於NSOperation對象能夠會在任什麼時候候運轉,是以轉變NSOperation對象的依附或數據會發生晦氣的影響。你只能檢查NSOperation對象的狀況, 好比能否正在運轉、期待運轉、曾經完成等
3、添加NSOperation的依附對象
1.當某個NSOperation對象依附於其它NSOperation對象的完成時,便可以經由過程addDependency辦法添加一個或許多個依附的對象,只要一切依附的對象都曾經完成操作,以後NSOperation對象才會開端履行操作。別的,經由過程removeDependency辦法來刪除依附對象。
[operation2 addDependency:operation1];
依附關系不局限於雷同queue中的NSOperation對象,NSOperation對象會治理本身的依附, 是以完整可以在分歧的queue之間的NSOperation對象創立依附關系
獨一的限制是不克不及創立環形依附,好比A依附B,B依附A,這是毛病的
2.依附關系會影響到NSOperation對象在queue中的履行次序,看上面的例子:
1> 沒有設置依附關系
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^(){
NSLog(@"履行第1次操作,線程:%@", [NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^(){
NSLog(@"履行第2次操作,線程:%@", [NSThread currentThread]);
}];
[queue addOperation:operation1];
[queue addOperation:operation2];
打印信息:
2013-02-03 00:21:35.024 thread[5616:3d13] 履行第1次操作,線程:<NSThread: 0x7658570>{name = (null), num = 3} 2013-02-03 00:21:35.063 thread[5616:1303] 履行第2次操作,線程:<NSThread: 0x765a2e0>{name = (null), num = 4}
可以看出,默許是依照添加次序履行的,先履行operation1,再履行operation2
2> 設置了依附關系
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^(){
NSLog(@"履行第1次操作,線程:%@", [NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^(){
NSLog(@"履行第2次操作,線程:%@", [NSThread currentThread]);
}];
// operation1依附於operation2
[operation1 addDependency:operation2];
[queue addOperation:operation1];
[queue addOperation:operation2];
打印信息:
2013-02-03 00:24:16.260 thread[5656:1b03] 履行第2次操作,線程:<NSThread: 0x7634490>{name = (null), num = 3} 2013-02-03 00:24:16.285 thread[5656:1303] 履行第1次操作,線程:<NSThread: 0x9138b50>{name = (null), num = 4}
可以看出,先履行operation2,再履行operation1
4、修正Operations的履行次序
關於添加到queue中的operations,它們的履行次序取決於2點:
1.起首看看NSOperation能否曾經預備好:能否預備好由對象的依附關系肯定
2.然後再依據一切NSOperation的絕對優先級來肯定。優先級品級則是operation對象自己的一個屬性。默許一切operation都具有“通俗”優先級,不外可以經由過程setQueuePriority:辦法來晉升或下降operation對象的優先級。優先級只能運用於雷同queue中的operations。假如運用有多個operation queue,每一個queue的優先級品級是相互自力的。是以分歧queue中的低優先級操作依然能夠比高優先級操作更早履行。
留意:優先級不克不及替換依附關系,優先級只是對曾經預備好的 operations肯定履行次序。先知足依附關系,然後再依據優先級從一切預備好的操作當選擇優先級最高的誰人履行。
5、設置隊列的最年夜並發操作數目
隊列的最年夜並發操作數目,意思是隊列中最多同時運轉幾條線程
固然NSOperationQueue類設計用於並發履行Operations,你也能夠強迫單個queue一次只能履行一個Operation。setMaxConcurrentOperationCount:辦法可以設置裝備擺設queue的最年夜並發操作數目。設為1就表現queue每次只能履行一個操作。不外operation履行的次序依然依附於其它身分,好比operation能否預備好和operation的優先級等。是以串行化的operation queue其實不同等於GCD中的串行dispatch queue
// 每次只能履行一個操作
queue.maxConcurrentOperationCount = 1;
// 或許如許寫
[queue setMaxConcurrentOperationCount:1];
6、撤消Operations
一旦添加到operation queue,queue就具有了這個Operation對象而且不克不及被刪除,獨一能做的工作是撤消。你可以挪用Operation對象的cancel辦法撤消單個操作,也能夠挪用operation queue的cancelAllOperations辦法撤消以後queue中的一切操作。
// 撤消單個操作
[operation cancel];
// 撤消queue中一切的操作
[queue cancelAllOperations];
7、期待Options完成
為了最好的機能,你應當設計你的運用盡量地異步操作,讓運用在Operation正在履行時可以行止理其它工作。假如須要在以後線程中處置operation完成後的成果,可使用NSOperation的waitUntilFinished辦法壅塞以後線程,期待operation完成。平日我們應當防止編寫如許的代碼,壅塞以後線程能夠是一種輕便的處理計劃,然則它引入了更多的串行代碼,限制了全部運用的並發性,同時也下降了用戶體驗。相對不要在運用主線程中期待一個Operation,只能在第二或主要線程中期待。壅塞主線程將招致運用沒法呼應用戶事宜,運用也將表示為無呼應。
// 會壅塞以後線程,比及某個operation履行終了
[operation waitUntilFinished];
除期待單個Operation完成,你也能夠同時期待一個queue中的一切操作,應用NSOperationQueue的waitUntilAllOperationsAreFinished辦法。留意:在期待一個 queue時,運用的其它線程依然可以往queue中添加Operation,是以能夠會加長線程的期待時光。
// 壅塞以後線程,期待queue的一切操作履行終了
[queue waitUntilAllOperationsAreFinished];
8、暫停和持續queue
假如你想暫時暫停Operations的履行,可使用queue的setSuspended:辦法暫停queue。不外暫停一個queue不會招致正在履行的operation在義務半途暫停,只是簡略地阻攔調劑新Operation履行。你可以在呼應用戶要求時,暫停一個queue來暫停期待中的義務。稍後依據用戶的要求,可以再次挪用setSuspended:辦法持續queue中operation的履行
// 暫停queue
[queue setSuspended:YES];
// 持續queue
[queue setSuspended:NO];
【Objective-C的NSOperation多線程類根本應用指南】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!