一、NSOperation簡介
相對於前面所說的NSThread,NSOperation同樣用於多線程,但是相比較而言,NSOperation是更高級別的類,它大大的簡化了處理多線程的過程,但是NSOperation是一個抽象基類,如果需要使用它的話,必須使用它的字累,或者自定義子類繼承NSOperation,實現內部響應的方法。在此之前稍稍補充幾個術語。
異步:不用阻塞當前線程來等待處理完成,而是允許後續操作,直至其它線程將處理完成,並回調通知此線程,不需要佔用額外線程。
同步:對在一個系統中所發生的事件之間進行協調,在時間上出現一致性與統一化
線程 :是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程自己不擁有系統資源。
進程:是系統進行資源分配和調度的基本單位。
並行:一組程序按獨立異步的速度執行。
併發:指一個時間段中有幾個程序都處於已啓動運行到運行完畢之間,且這幾個程序都是在同一個處理機上運行,但任一個時刻點上只有一個程序在處理機上運行。
二、使用NSOperation實現多線程的具體步驟
1) 先將需要執行的操作封裝到一個NSOperation對象中;
2) 兩種方式調用NSOperation;
2.1) NSOperation調用start方法執行任務,但默認是同步的;
2.2)將NSOperation對象添加到NSOperationQueue中,系統會自動異步執行NSOperation中的操作;
2.2.1)系統會自動將NSOperationQueue中的NSOperation取出來;
2.2.2)NSOperationQueue會開闢一條新線程,將取出的NSOperation封裝的操作進行執行。
三、NSOperation的子類
1. NSInvocationOperation
2. NSBlockOperation
3. 自定義NSOperation子類
四、NSOperation相關操作
a.執行操作
NSOperation調用start方法即可開始執行操作,NSOperation對象默認按同步方式執行,也就是在調用start方法的那個線程中直接執行。NSOperation對象的isConcurrent方法會告訴我們這個操作相對於調用start方法的線程,是同步還是異步執行。isConcurrent方法默認返回NO,表示操作與調用線程同步執行。
[operation start];
b.取消操作[operation cancel];
c.監聽執行操作operation.completionBlock = ^(){
NSLog(@"%s",__func__);
};
或[operation setCompletionBlock:^{
NSLog(@"%s",__func__);
}];
五、NSOperation子類的使用a.NSInvocationOperation
NSInvocationOperation是基於一個對象和selector來創建操作的。如果你已經有現有的方法來執行需要的任務,就可以使用這個類。
創建並執行的操作
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
[operation start];
- (void)run
{
NSLog(@"---%@---",[NSThread currentThread]);
}
b.NSBlockOperation
NSBlockOperation能夠併發地執行一個或多個block對象,所有相關的block都執行完之後,操作纔算完成。
// 創建NSBlockOperation對象
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){
NSLog(@"線程1=====%@", [NSThread currentThread]);
}];
// 通過addExecutionBlock方法添加block操作
[operation addExecutionBlock:^{
NSLog(@"線程2=====%@",[NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"線程3=====%@",[NSThread currentThread]);
}];
// 開始執行任務(這裏還是同步執行)
[operation start];
c.自定義NSOperation子類
如果NSInvocationOperation和NSBlockOperation都不能夠滿足需求,那麼就只能自定義繼承於NSOperation的子類了,繼承NSOperation需要重寫NSOperation的基本方法。
例子:
.h文件
@interface PPDownLoadOperation : NSOperation
@property(nonatomic,copy)NSString *url;
@property(nonatomic,weak)id delegate;
@end
@protocol PPDownLoadOperationDelegate <NSObject>
- (void)didFishedDownLoadImage:(UIImage *)image;
@end
.m文件-(void)main
{
@autoreleasepool {
if (self.isCancelled) {
return;
}
NSURL *url = [NSURL URLWithString:self.url];
NSData *data = [NSData dataWithContentsOfURL:url];
if (self.isCancelled) {
url = nil;
data = nil;
return;
}
UIImage *imgae=[UIImage imageWithData:data];
if (self.isCancelled) {
imgae = nil;
return;
}
//圖片下載完畢後,通知代理
if ([self.delegate respondsToSelector:@selector(didFishedDownLoadImage:)])
{
dispatch_async(dispatch_get_main_queue(), ^{//回到主線程,傳遞數據給代理對象
[self.delegate didFishedDownLoadImage:imgae];
});
}
}
}