概述多线程(NSOperation和NSOperationQueue) 在网络应用程序中,经常要使用多任务处理来提高应用程序的性能,即在同一时间,有多个处理同时进行。例如,同时进行多个文件下载,同时进行多个HTTP请求等。这一般都 是通过多线程完成的。另外,多线程编程也是为了防止主线程堵塞,增加运行效率的方法。比如,如果主线程从网上下载一个很大的图片,那么,给用户的感觉是整个应用程序死掉了。所以,可以 多线程(NSOperation和NSOperationQueue)
在网络应用程序中,经常要使用多任务处理来提高应用程序的性能,即在同一时间,有多个处理同时进行。例如,同时进行多个文件下载,同时进行多个http请求等。这一般都 是通过多线程完成的。另外,多线程编程也是为了防止主线程堵塞,增加运行效率的方法。比如,如果主线程从网上下载一个很大的图片,那么,给用户的感觉是整个应用程序死掉了。所以,可以把这个下载 *** 作放在一个线程中,在主线程中调用这个线程让它在后台处理,主线程序可以显示一些其他信息,比如显示一些“正在装载”等文字信息。
在Cocoa中,NSOperation类提供了一个优秀的多线程编程方法。很多编程语言都支持多线程处理应用程序,但是多线程程序往往一旦出错就会很难处理。庆幸的是,苹果公司在这方面做了很多改进,例如在NSThread上新增了很多方法,还新增了两个类NSOperation 和NSOperationQueue,从而让多线程处理变得更加容易。
在多线程中,可以同时进行多个 *** 作。NSOperation对象就是一个 *** 作,比如,装载网页内容的一个 *** 作。在Objective-C上,一个具体的 *** 作(比如网页装载)是一个继承NSOperation 的类。在这个类中,至少需要重写一个-(voID)main方法。线程(NSOperation)自动调用main 方法,main方法就是线程要执行的具体 *** 作。在下面的例子中,PageLoadOperation 继承了NSOperation,并实现了main方法。一般而言,可以利用其初始化方法来传入所需要的参数和对象,比如PageLoadOperation的initWithURL:方法用来设置要装载的网址。
使用NSOperation 的最简单方法就是将其放入NSOperationQueue中,NSOperationQueue是存放多个 *** 作的队列。一旦一个NSOperation对象被加入NSOperationQueue,该队列就会启动并开始处理它(即调用它的main方法),当 *** 作完成后,队列就会释放它。
下面创建一个CocoaApplication例子来演示使用NSOperation和NSOperationQueue完成多线程处理。
应用代理类AppDelegate.h的代码如下:
#import<Cocoa/Cocoa.h>
@interface AppDelegate : NSObject {
NSOperationQueue *queue; //线程队列
}
+ (ID)shared;
- (voID)pageLoaded:(NSXMLdocument*)document;
@end
AppDelegate.m的代码如下:
#import "AppDelegate.h"
#import "PageLoadOperation.h"
@implementation AppDelegate
static AppDelegate *shared;
static NSArray *urlArray;
- (ID)init
{
if (shared) {
[self autorelease];
return shared;
}
if (![super init]) return nil;
//设置要访问的网址
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addobject:@"http://www.xinlaoshi.com"];
[array addobject:@"http://www.yunwenjian.com"];
[array addobject:@"http://www.108fang.com"];
[array addobject:@"http://www.baIDu.com"];
urlArray = array;
//[queue setMaxConcurrentoperatio
nCount:2]; queue = [[NSOperationQueue alloc] init];
shared = self;
return self;
}
- (voID)applicationDIDFinishLaun
ching:(NSNotification*)aNotification { //把各个 *** 作添加到队列中
for (Nsstring *urlString in urlArray) {
NSURL *url = [NSURL URLWithString:urlString];
PageLoadOperation *plo = [[PageLoadOperation alloc]
initWithURL:url];
[queue addOperation:plo];
[plo release];
}
}
- (voID)dealloc
{
[queue release],queue = nil;
[super dealloc];
}
+ (ID)shared;
{
if (!shared) {
[[AppDelegate alloc] init];
}
return shared;
}
//用于打印网页内容
- (voID)pageLoaded:(NSXMLdocument*)document;
{
NSLog(@"xml 文档是:%@",document);
}
@end
线程 *** 作类PageLoadOperation.h的代码如下:
#import<Cocoa/Cocoa.h>
@interface PageLoadOperation : NSOperation {
//需要使用多线程的类要继承NSOperation
NSURL *targetURL;
}
@property(retain) NSURL *targetURL;
- (ID)initWithURL:(NSURL*)url;
@end
PageLoadOperation.m的代码如下:
#import "PageLoadOperation.h"
#import "AppDelegate.h"
@implementation PageLoadOperation
@synthesize targetURL;
//获取要访问的网址
- (ID)initWithURL:(NSURL*)url;
{
if (![super init]) return nil;
[self setTargetURL:url];
return self;
}
- (voID)dealloc {
[targetURL release],targetURL = nil;
[super dealloc];
}
//线程完成的 *** 作。本例访问网址,并把该网址的内容放到一个NSXMLdocument 对象上
- (voID)main {
//将targetURL 的值返回为webpageString 对象
Nsstring *webpageString = [[[Nsstringalloc]initWithContentsOfURL:
[self targetURL]] autorelease];
NSError *error = nil;
//访问网址,并把该网址的网页内容放到一个NSXMLdocument 对象上
NSXMLdocument *document = [[NSXMLdocument alloc]initWithXMLString:
webpageString options:NSXMLdocumentTIDyHTMLerror:&error];
if (!document) {
//当document 为nil 的时候打印错误信息
NSLog(@"错误信息:(%@): %@",[[self targetURL] absoluteString],
error);
return;
}
//拿到AppDelegate 对象并且调用主线程上的打印方法
[[AppDelegate shared]
performSelectorOnMainThr
ead:@selector(pageLoaded:) withObject:document
waitUntilDone:NO];
}
@end
【程序结果】
xml 文档是:<!DOCTYPE HTML PUBliC "-//W3C//DTDxhtml 1.0
Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-
Transitional.dtd"><HTMLxmlns=" http://www.w3.org/1999/xhtml"><head><Meta
http-equiv="Content-Type" content=" text/HTML; charset=utf-8"/><Title>新老
师-学网上课程交圈内朋友</Title>
....
xml 文档是:<!DOCTYPE HTML PUBliC "-//W3C//DTDxhtml 1.0
Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-
Transitional.dtd"><HTML><head><Title>云文件</Title>
....
xml 文档是:<!DOCTYPE HTML PUBliC "-//W3C//DTDxhtml 1.0
Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-
Transitional.dtd"><HTMLxmlnsHTMLxmlns=" http://www.w3.org/1999/xhtml"><head><Meta
http-equiv="Content-Type" content="text/HTML; charset=utf-8"/>
<Title>108方手机应用平台</Title>
....
xml 文档是:<!DOCTYPEHTML><HTML><head><Metahttp-equiv="Content-Type"
content="text/HTML;charset=gb2312"><Title>百度一下,你就知道</Title>
下面分析一下这段程序执行过程,由于是一个Cocoa Application应用程序,所以系统会先执行委托类AppDelegate 下的初始化方法- (ID)init进行一些初始化设置。在这个委托方法上,首先判断shared是否已经初始化过。若初始化过,则直接返回结果;若是应用程序第一次调用初始化方法,则就初始化urlArray数组,并将要用线程访问的各个网站地址装入其中,随后初始化shred 和NSOperationQueue的对象queue。在应用装载结束以后,系统会调用另一个委托方法applicationDIDFinishLaun
ching:方法,在这个方法中,我们遍历存入urlArray数组中的网站地址字符串,将其依次转换为NSURL对象。与此同时,创建同等数量的PageLoadOperation对象,并将转换好的NSURL 对象设置为各个PageLoadOperation对象的属性targetURL。我们还将初始化好的PageLoadOperation对象加入到queue队列上。 在队列中每加入一个线程 *** 作后,队列都会为其分配一个NSThread来启动它,并运行 *** 作的main方法。一旦 *** 作完成,线程就会报告给队列以让队列释放该 *** 作。
在PageLoadOperation 类的main 方法上,根据前面设置好的targetURL属性值,将该网址转换为字符串对象webpageString,并且加入自动释放池。利用转换好的webpageString对象初始化NSXMLdocument对象,并访问这个网站,把内容放在NSXMLdocument对象上。如果在加载网站内容过程中发生错误,就会打印错误信息。如果没有错误,就调用主线程的pageLoaded方法,从而打印网页内容到控制台上,然后任务结束。队列会在main 方法结束后自动释放该线程。
这个例子展示了NSOperation 和NSOperationQueue最基本的使用。实例中的大部分代码与NSOperation 和NSOperationQueue的设定和使用无关,都是一些业务实现代码。NSOperation本身所需要的代码非常少,但是通过这少量的代码就可以在应用中轻松地使用多线程,从而为用户提供更好的并发性能。另外,在init方法中,有一句代码:
//[queuesetMaxConcurrentoperatio
nCount:2]; 这是用来设置线程的个数。如果去掉上面的注释,那么,线程队列就被限制为只能同时运行两个 *** 作,剩余的 *** 作就需要等待这两个 *** 作中的任一个完成后才有可能被运行。 总结
以上是内存溢出为你收集整理的NSOperation和NSOperationQueue全部内容,希望文章能够帮你解决NSOperation和NSOperationQueue所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
评论列表(0条)