`
ydbc
  • 浏览: 718293 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

多线程(NSOperation和NSOperationQueue)

 
阅读更多





《objective-c程序设计》第11章AppKit和UIKit,在前面十章,我们都是使用NSLog 在控制台上输出结果。在iPhone/iPad 上,所有的应用程序都有图形化界面。正如我们在第一章所提到的,Xcode 同Interface Builder(界面创建器)集成在一起,通过界面创建器,读者可以创建图形化用户界面。Xcode 还提供了调试工具,帮助你开发Objective-C应用程序。本节为大家介绍多线程(NSOperation和NSOperationQueue)。

AD:

11.4 多线程(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方法),当操作完成后,队列就会释放它。

下面创建一个Cocoa Application例子来演示使用NSOperation和NSOperationQueue完成多线程处理。

应用代理类AppDelegate.h的代码如下:

  1. #import<Cocoa/Cocoa.h>
  2. @interfaceAppDelegate:NSObject{
  3. NSOperationQueue*queue;//线程队列
  4. }
  5. +(id)shared;
  6. -(void)pageLoaded:(NSXMLDocument*)document;
  7. @end
  8. AppDelegate.m的代码如下:
  9. #import"AppDelegate.h"
  10. #import"PageLoadOperation.h"
  11. @implementationAppDelegate
  12. staticAppDelegate*shared;
  13. staticNSArray*urlArray;
  14. -(id)init
  15. {
  16. if(shared){
  17. [selfautorelease];
  18. returnshared;
  19. }
  20. if(![superinit])returnnil;
  21. //设置要访问的网址
  22. NSMutableArray*array=[[NSMutableArrayalloc]init];
  23. [arrayaddObject:@"http://www.xinlaoshi.com"];
  24. [arrayaddObject:@"http://www.yunwenjian.com"];
  25. [arrayaddObject:@"http://www.108fang.com"];
  26. [arrayaddObject:@"http://www.baidu.com"];
  27. urlArray=array;
  28. //[queuesetMaxConcurrentOperationCount:2];
  29. queue=[[NSOperationQueuealloc]init];
  30. shared=self;
  31. returnself;
  32. }
  33. -(void)applicationDidFinishLaunching:(NSNotification*)aNotification
  34. {//把各个操作添加到队列中
  35. for(NSString*urlStringinurlArray){
  36. NSURL*url=[NSURLURLWithString:urlString];
  37. PageLoadOperation*plo=[[PageLoadOperationalloc]
  38. initWithURL:url];
  39. [queueaddOperation:plo];
  40. [plorelease];
  41. }
  42. }
  43. -(void)dealloc
  44. {
  45. [queuerelease],queue=nil;
  46. [superdealloc];
  47. }
  48. +(id)shared;
  49. {
  50. if(!shared){
  51. [[AppDelegatealloc]init];
  52. }
  53. returnshared;
  54. }
  55. //用于打印网页内容
  56. -(void)pageLoaded:(NSXMLDocument*)document;
  57. {
  58. NSLog(@"xml文档是:%@",document);
  59. }
  60. @end

线程操作类PageLoadOperation.h的代码如下:

  1. #import<Cocoa/Cocoa.h>
  2. @interfacePageLoadOperation:NSOperation{
  3. //需要使用多线程的类要继承NSOperation
  4. NSURL*targetURL;
  5. }
  6. @property(retain)NSURL*targetURL;
  7. -(id)initWithURL:(NSURL*)url;
  8. @end
  9. PageLoadOperation.m的代码如下:
  10. #import"PageLoadOperation.h"
  11. #import"AppDelegate.h"
  12. @implementationPageLoadOperation
  13. @synthesizetargetURL;
  14. //获取要访问的网址
  15. -(id)initWithURL:(NSURL*)url;
  16. {
  17. if(![superinit])returnnil;
  18. [selfsetTargetURL:url];
  19. returnself;
  20. }
  21. -(void)dealloc{
  22. [targetURLrelease],targetURL=nil;
  23. [superdealloc];
  24. }
  25. //线程完成的操作。本例访问网址,并把该网址的内容放到一个NSXMLDocument对象上
  26. -(void)main{
  27. //将targetURL的值返回为webpageString对象
  28. NSString*webpageString=[[[NSStringalloc]initWithContentsOfURL:
  29. [selftargetURL]]autorelease];
  30. NSError*error=nil;
  31. //访问网址,并把该网址的网页内容放到一个NSXMLDocument对象上
  32. NSXMLDocument*document=[[NSXMLDocumentalloc]initWithXMLString:
  33. webpageStringoptions:NSXMLDocumentTidyHTMLerror:&error];
  34. if(!document){
  35. //当document为nil的时候打印错误信息
  36. NSLog(@"错误信息:(%@):%@",[[selftargetURL]absoluteString],
  37. error);
  38. return;
  39. }
  40. //拿到AppDelegate对象并且调用主线程上的打印方法
  41. [[AppDelegateshared]
  42. performSelectorOnMainThread:@selector(pageLoaded:)
  43. withObject:document
  44. waitUntilDone:NO];
  45. }
  46. @end

【程序结果】

  1. xml文档是:<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0
  2. Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-
  3. transitional.dtd"><htmlxmlns="
    http://www.w3.org/1999/xhtml"
    ><head><meta
  4. http-equiv="Content-Type"content="
    text/html;charset=utf-8"
    /><title>新老
  5. 师-学网上课程交圈内朋友</title>
  6. ....
  7. xml文档是:<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0
  8. Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-
  9. transitional.dtd"><html><head><title>云文件</title>
  10. ....
  11. xml文档是:<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0
  12. Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-
  13. transitional.dtd"><htmlxmlnshtmlxmlns="
    http://www.w3.org/1999/xhtml"
    ><head><meta
  14. http-equiv="Content-Type"content="text/html;charset=utf-8"/>
  15. <title>108方手机应用平台</title>
  16. ....
  17. xml文档是:<!doctypehtml><html><head><metahttp-equiv="Content-Type"
  18. content="text/html;charset=gb2312"><title>百度一下,你就知道</title>

下面分析一下这段程序执行过程,由于是一个Cocoa Application 应用程序,所以系统会先执行委托类AppDelegate 下的初始化方法- (id)init 进行一些初始化设置。在这个委托方法上,首先判断shared 是否已经初始化过。若初始化过,则直接返回结果;若是应用程序第一次调用初始化方法,则就初始化urlArray 数组,并将要用线程访问的各个网站地址装入其中,随后初始化shred 和NSOperationQueue 的对象queue。在应用装载结束以后,系统会调用另一个委托方法applicationDidFinishLaunching:方法,在这个方法中,我们遍历存入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方法中,有一句代码:

  1. //[queuesetMaxConcurrentOperationCount:2];

这是用来设置线程的个数。如果去掉上面的注释,那么,线程队列就被限制为只能同时运行两个操作,剩余的操作就需要等待这两个操作中的任一个完成后才有可能被运行。

分享到:
评论

相关推荐

    iOS多线程与网络开发之NSOperation示例代码

    配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation对象中 然后将NSOperation对象添加到NSOperationQueue中 ...

    iOS多线程应用开发中使用NSOperation类的基本方法

    NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤: (1)先将需要执行的操作封装到一个NSOperation对象中 (2)然后将NSOperation...

    ios多线程开发的常用四种方式和基本使用

    ios多线程开发的常用四种方式和基本使用,pthread、NSThread、NSOperation\NSOperationQueue、GCD

    ios的三种多线程技术

    #iOS的三种多线程技术 和特性 1.NSThread 2.NSOperation/NSOperationQueue 3.GCD (大中心调度)

    iOS 多线程总结

    对iOS的多线程方式做的总结;Pthreads,NSThread,GCD,NSOperation/NSOperationQueue

    IOS编程中使用多线程

    在app store中的很多应用程序非常的笨重,他们有好的界面,但操作性很差,比如说当程序从网上或本地载入数据的时候,界面被冻结了,用户只能等...除此之外,它们还引入了两个全新的类,NSOperation和NSOperationQueue。

    使用GCD和NSOperation的自我感悟(部分用法和tips)

    GCD(Grand Central Dispatch):基于C语言,属于更底层的多线程技术,所以在效率上的优势比较明显;依赖于Block执行任务也使得开发上变得更简单,方便开发者看到任务的上下文。  NSOperation和NSOperationQueue:...

    IOS多线程编程系类

    1.、NSThread2、CocoaNSOperation(IOS多线程编程之NSOperation和NSOperationQueue的使用)3、GCD全称:GrandCentralDispatch(IOS多线程编程之Grand CentralDispatch(GCD)介绍和使用)这三种编程方式从上到下,抽象...

    IOS多线程编程的3种实现方法

    NSOperation和NSOperationQueue 1.NSThread 这是最轻量级的多线程的方法,使用起来最直观的多线程编程方法。但是因为需要自己管理线程的生命周期,线程同步。经常使用NSThread进行调试,在实际项目中不推荐使用。 ...

    iOS并发编程指南.pdf

    苹果官方文档的翻译,详细讲解。NSOperation+NSOperationQueue,GCD+dispatch_queue,RunLoop等详细介绍。

    iOS多线程编程之NSThread的使用案例

    2、Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue的使用)3、GCD 全称:Grand Central Dispatch( iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用) 这三种编程方式从上到下,抽象度...

    在IOS中为什么使用多线程及多线程实现的三种方法

    给大家介绍在IOS中为什么使用多线程及多线程实现的三种方法,基本上使用这三种方法实现多线程(NSThread Grand Centeral Dispatch(GCD) NSOperation和NSOperationQueue),感兴趣的朋友可以参考下本

    leetcode答案-iOS-:在网上找的一些iOS面试资料

    leetcode 答案 iOS- 在网上找的一些iOS面试资料 1、2018 iOS面试题---UI相关:事件传递,...iOS面试题-----多线程相关之NSOperation、NSOperationQueue、NSThread+runloop实现常驻线程、加锁 10、2019 iOS面试题-----R

    YXQueue:适用于iOS的OOP和轻松使用作业队列

    YXQueue适用于iOS的OOP和轻松使用作业队列YXQueue被封装用于NSOperation。 线程的管理器和调用者按YXQueue划分。 使用它,开发人员将不会太在意线程管理,而只是关注如何创建作业和实现委托。建筑学...

    UIImage-Cache:对SDWebImage的缓存机制做了封装

    3、使用NSOperation来进行多线程下载文件,将每次的下载操作放到NSOperationQueue中,并在图片下载成功后将当前下载操作从操作缓冲池中移除。(用来模拟网络较慢的情况下,Swift拖动cell进出显示区域造成的线程多次...

Global site tag (gtag.js) - Google Analytics