`
feipigwang
  • 浏览: 770227 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

多线程(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];

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

分享到:
评论

相关推荐

    NSOperation_NSOperationQueue_Demo

    NSOperation和NSOperationQueue是Apple在iOS和macOS开发中提供的多线程处理框架,用于高效管理和调度异步任务。这两个类是Foundation框架的一部分,旨在简化并发编程,提高应用程序的性能和响应性。 **NSOperation*...

    iOS 多线程NSoperation

    NSOperation是Apple提供的一个高级多线程框架,它基于GCD(Grand Central Dispatch)并提供了更强大的功能和灵活性。本篇文章将深入探讨iOS多线程中的NSOperation及其相关知识点。 一、NSOperation简介 NSOperation...

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

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

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

    NSOperation和NSOperationQueue是Apple推荐的多线程解决方案,它们提供了更高级别的抽象和任务调度。NSOperation是一个抽象基类,代表一个可执行的操作。开发者可以继承自定义操作,添加逻辑,并控制操作的依赖关系...

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

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

    iOS-多线程之NSOperation - iOS知识库1

    iOS提供了多种实现多线程的方式,包括NSThread、GCD(Grand Central Dispatch)以及NSOperation和NSOperationQueue。 NSOperation是苹果提供的一种更加面向对象的多线程解决方案,它比GCD更易于理解和使用,特别是...

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

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

    iOS 多线程总结

    本文将深入探讨四种主要的iOS多线程机制:Pthreads、NSThread、GCD(Grand Central Dispatch)以及NSOperation和NSOperationQueue。 首先,Pthreads是POSIX线程库的一部分,支持跨平台的多线程编程。在iOS中,虽然...

    iOS开发学习之iOS多线程和RunLoop.pdf

    总的来说,iOS开发中的多线程技术涉及NSThread、POSIX Thread、NSOperation与NSOperationQueue以及GCD等,它们各有优势和使用场景。而RunLoop是管理线程生命周期的关键组件,对于理解iOS应用性能优化至关重要。掌握...

    同步和异步的NSOperation的Demo

    NSOperation和NSOperationQueue是iOS和Mac OS X开发中用于实现多任务并行处理的关键框架,它们是苹果提供的高级并发工具,旨在简化复杂的线程...通过实践和学习这个Demo,开发者可以更好地掌握多线程编程和并发管理。

    ios的三种多线程技术

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

    ios多线程开发

    NSOperation和NSOperationQueue是面向对象的多线程模型,相对于GCD更易理解和使用。NSOperation是对操作的抽象,可以设置依赖、取消、优先级等属性。NSOperationQueue负责调度和执行操作,支持最大并发数限制,可以...

    swift-这里详细介绍了iOS多线程NSThreadGCDNSOperation的使用

    最后,NSOperation和NSOperationQueue是面向对象的多线程解决方案。NSOperation是一个抽象基类,你可以通过继承它来定义自己的操作。与NSThread不同,NSOperation不仅关注线程,还关注任务本身。你可以设置依赖关系...

    IOS多线程理解

    本文将深入探讨iOS的三种主要多线程编程方式:NSThread、NSOperation和NSOperationQueue,以及Grand Central Dispatch (GCD)。 首先,NSThread是iOS中的一种基本线程实现。通过创建NSThread对象,我们可以简单地...

    iOS并发编程指南.pdf.zip

    GCD提供基础的异步编程能力,NSOperation和NSOperationQueue则增加了更多的控制和灵活性。理解和熟练运用这些工具,将有助于你编写出高效、稳定、用户体验优秀的iOS应用。通过深入学习“iOS并发编程指南”,开发者...

    IOS应用源码之多线程 .rar

    多线程环境下,数据访问和修改可能会引发竞态条件,因此需要确保线程安全。iOS提供了一些机制,如锁(@synchronized关键字)、自旋锁、读写锁等来保护共享资源。此外,还要注意内存管理,避免因线程间交互导致的内存...

    多线程GCD,NSThread,NSOperationQueue,详细解释Demo

    本篇文章将深入探讨GCD (Grand Central Dispatch)、NSThread和NSOperationQueue这三种主要的多线程实现方式,并通过具体示例进行详细解释。 **一、GCD(Grand Central Dispatch)** GCD是Apple开发的一种多线程...

    演示多线程加载图片NSThread NsOperation GCD

    本教程将重点讲解三种多线程技术:NSThread、NSOperation和GCD(Grand Central Dispatch),以及如何用它们来实现图片的异步加载。 首先,我们来看`NSThread`。`NSThread`是Apple提供的轻量级线程管理类,允许...

    NSOperation

    NSOperation是iOS和macOS开发中的一个核心组件,属于Foundation框架的一部分,主要用于实现多线程编程,以提高应用程序的性能和响应性。它提供了一种更高级、更灵活的方式来管理和组织并发任务,尤其是在处理大量...

Global site tag (gtag.js) - Google Analytics