生活随笔
收集整理的這篇文章主要介紹了
多线程编程2 - NSOperation
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
一、NSOperation
1.簡介
NSOperation實(shí)例封裝了需要執(zhí)行的操作和執(zhí)行操作所需的數(shù)據(jù),并且能夠以并發(fā)或非并發(fā)的方式執(zhí)行這個(gè)操作。
NSOperation本身是抽象基類,因此必須使用它的子類,使用NSOperation子類的方式有2種:
1> Foundation框架提供了兩個(gè)具體子類直接供我們使用:NSInvocationOperation和NSBlockOperation
2> 自定義子類繼承NSOperation,實(shí)現(xiàn)內(nèi)部相應(yīng)的方法
2.執(zhí)行操作
NSOperation調(diào)用start方法即可開始執(zhí)行操作,NSOperation對(duì)象默認(rèn)按同步方式執(zhí)行,也就是在調(diào)用start方法的那個(gè)線程中直接執(zhí)行。NSOperation對(duì)象的isConcurrent方法會(huì)告訴我們這個(gè)操作相對(duì)于調(diào)用start方法的線程,是同步還是異步執(zhí)行。isConcurrent方法默認(rèn)返回NO,表示操作與調(diào)用線程同步執(zhí)行
3.取消操作
operation開始執(zhí)行之后, 默認(rèn)會(huì)一直執(zhí)行操作直到完成,我們也可以調(diào)用cancel方法中途取消操作
[java]?view plaincopy
[operation?cancel];??
4.監(jiān)聽操作的執(zhí)行
如果我們想在一個(gè)NSOperation執(zhí)行完畢后做一些事情,就調(diào)用NSOperation的setCompletionBlock方法來設(shè)置想做的事情
[java]?view plaincopy
operation.completionBlock?=?^()?{?? ????NSLog(@"執(zhí)行完畢");?? };??
或者
[java]?view plaincopy
[operation?setCompletionBlock:^()?{?? ????NSLog(@"執(zhí)行完畢");?? }];??
二、NSInvocationOperation
1.簡介
基于一個(gè)對(duì)象和selector來創(chuàng)建操作。如果你已經(jīng)有現(xiàn)有的方法來執(zhí)行需要的任務(wù),就可以使用這個(gè)類
2.創(chuàng)建并執(zhí)行操作
[java]?view plaincopy
?? NSInvocationOperation?*operation?=?[[NSInvocationOperation?alloc]?initWithTarget:self?selector:@selector(run)?object:nil];?? ?? [operation?start];??
三、NSBlockOperation
1.簡介
能夠并發(fā)地執(zhí)行一個(gè)或多個(gè)block對(duì)象,所有相關(guān)的block都執(zhí)行完之后,操作才算完成
2.創(chuàng)建并執(zhí)行操作
[java]?view plaincopy
NSBlockOperation?*operation?=?[NSBlockOperation?blockOperationWithBlock:^(){?? ????????NSLog(@"執(zhí)行了一個(gè)新的操作,線程:%@",?[NSThread?currentThread]);?? }];?? ??? [operation?start];??
3.通過addExecutionBlock方法添加block操作
[java]?view plaincopy
NSBlockOperation?*operation?=?[NSBlockOperation?blockOperationWithBlock:^(){?? ????NSLog(@"執(zhí)行第1次操作,線程:%@",?[NSThread?currentThread]);?? }];?? ?? [operation?addExecutionBlock:^()?{?? ????NSLog(@"又執(zhí)行了1個(gè)新的操作,線程:%@",?[NSThread?currentThread]);?? }];?? ?? [operation?addExecutionBlock:^()?{?? ????NSLog(@"又執(zhí)行了1個(gè)新的操作,線程:%@",?[NSThread?currentThread]);?? }];?? ?? [operation?addExecutionBlock:^()?{?? ????NSLog(@"又執(zhí)行了1個(gè)新的操作,線程:%@",?[NSThread?currentThread]);?? }];?? ?? ?? [operation?start];??
打印信息如下:
[java]?view plaincopy
2013-02-02?21:38:46.102?thread[4602:c07]?又執(zhí)行了1個(gè)新的操作,線程:<NSThread:?0x7121d50>{name?=?(null),?num?=?1}?? 2013-02-02?21:38:46.102?thread[4602:3f03]?又執(zhí)行了1個(gè)新的操作,線程:<NSThread:?0x742e1d0>{name?=?(null),?num?=?5}?? 2013-02-02?21:38:46.102?thread[4602:1b03]?執(zhí)行第1次操作,線程:<NSThread:?0x742de50>{name?=?(null),?num?=?3}?? 2013-02-02?21:38:46.102?thread[4602:1303]?又執(zhí)行了1個(gè)新的操作,線程:<NSThread:?0x7157bf0>{name?=?(null),?num?=?4}??
可以看出,這4個(gè)block是并發(fā)執(zhí)行的,也就是在不同線程中執(zhí)行的,num屬性可以看成是線程的id
四、自定義NSOperation
1.簡介
如果NSInvocationOperation和NSBlockOperation對(duì)象不能滿足需求, 你可以直接繼承NSOperation, 并添加任何你想要的行為。繼承所需的工作量主要取決于你要實(shí)現(xiàn)非并發(fā)還是并發(fā)的NSOperation。定義非并發(fā)的NSOperation要簡單許多,只需要重載-(void)main這個(gè)方法,在這個(gè)方法里面執(zhí)行主任務(wù),并正確地響應(yīng)取消事件; 對(duì)于并發(fā)NSOperation, 你必須重寫NSOperation的多個(gè)基本方法進(jìn)行實(shí)現(xiàn)(這里暫時(shí)先介紹非并發(fā)的NSOperation)
2.非并發(fā)的NSOperation
比如叫做DownloadOperation,用來下載圖片
1> 繼承NSOperation,重寫main方法,執(zhí)行主任務(wù)
DownloadOperation.h
[java]?view plaincopy
#import?<Foundation/Foundation.h>?? @protocol?DownloadOperationDelegate;?? ?? @interface?DownloadOperation?:?NSOperation?? ?? @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
[java]?view plaincopy
#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> 正確響應(yīng)取消事件
operation開始執(zhí)行之后,會(huì)一直執(zhí)行任務(wù)直到完成,或者顯式地取消操作。取消可能發(fā)生在任何時(shí)候,甚至在operation執(zhí)行之前。盡管NSOperation提供了一個(gè)方法,讓應(yīng)用取消一個(gè)操作,但是識(shí)別出取消事件則是我們自己的事情。如果operation直接終止, 可能無法回收所有已分配的內(nèi)存或資源。因此operation對(duì)象需要檢測取消事件,并優(yōu)雅地退出執(zhí)行
NSOperation對(duì)象需要定期地調(diào)用isCancelled方法檢測操作是否已經(jīng)被取消,如果返回YES(表示已取消),則立即退出執(zhí)行。不管是自定義NSOperation子類,還是使用系統(tǒng)提供的兩個(gè)具體子類,都需要支持取消。isCancelled方法本身非常輕量,可以頻繁地調(diào)用而不產(chǎn)生大的性能損失
以下地方可能需要調(diào)用isCancelled:
* 在執(zhí)行任何實(shí)際的工作之前
* 在循環(huán)的每次迭代過程中,如果每個(gè)迭代相對(duì)較長可能需要調(diào)用多次
* 代碼中相對(duì)比較容易中止操作的任何地方
DownloadOperation的main方法實(shí)現(xiàn)如下
[java]?view plaincopy
-?(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];?? ????????}?? ????}?? } ?
總結(jié)
以上是生活随笔為你收集整理的多线程编程2 - NSOperation的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。