多线程之NSThreadCocoa NSOperationGCD

Posted zhangyangsk8

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程之NSThreadCocoa NSOperationGCD相关的知识,希望对你有一定的参考价值。

ios多线程编程技术之NSThread、Cocoa NSOperation、GCD

发布于:2014-05-20 11:14阅读数:3142



转自 容芳志的博客   简介 iOS有三种多线程编程的技术,分别是: (一)NSThread  (二)Cocoa NSOperation (三)GCD(全称:Grand Central Dispatch)   这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的。   三种方式的优缺点介绍: 1) NSThread: 优点:NSThread 比其他两个轻量级 缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销   NSThread实现的技术有下面三种: 一般使用cocoa thread 技术。   Cocoa NSOperation 优点:不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上。 Cocoa operation 相关的类是 NSOperation ,NSOperationQueue。 NSOperation是个抽象类,使用它必须用它的子类,可以实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。 创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。   GCD Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。在iOS4.0开始之后才能使用。GCD是一个替代诸如NSThread, NSOperationQueue, NSInvocationOperation等技术的很高效和强大的技术。现在的iOS系统都升级到7了,所以不用担心该技术不能使用。   介绍完这三种多线程编程方式,本文将依次介绍这三种技术的使用。   (一)NSThread的使用 NSThread 有两种直接创建方式:
       
  1. - (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument 
  2. + (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument 
  第一个是实例方法,第二个是类方法
       
  1. 1、[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];   
  2.   
  3. 2、NSThread* myThread = [[NSThread alloc] initWithTarget:self   
  4.                                         selector:@selector(doSomething:)   
  5.                                         object:nil];   
  6. [myThread start];   
参数的意义: selector :线程执行的方法,这个selector只能有一个参数,而且不能有返回值。 target  :selector消息发送的对象 argument:传输给target的唯一参数,也可以是nil   第一种方式会直接创建线程并且开始运行线程,第二种方式是先创建线程对象,然后再运行线程操作,在运行线程操作前可以设置线程的优先级等线程信息   不显式创建线程的方法: 用NSObject的类方法  performSelectorInBackground:withObject: 创建一个线程:
       
  1. [Obj performSelectorInBackground:@selector(doSomething) withObject:nil]; 
  下载图片的例子: 新建singeView app 新建项目,并在xib文件上放置一个imageView控件。按住control键拖到viewController.h文件中创建imageView IBOutlet ViewController.m中实现: 
       
  1. //   
  2. //  ViewController.m   
  3. //  NSThreadDemo   
  4. //   
  5. //  Created by rongfzh on 12-9-23.   
  6. //  Copyright (c) 2012年 rongfzh. All rights reserved.   
  7. //   
  8.    
  9. #import "ViewController.h"   
  10. #define kURL @"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"   
  11. @interface ViewController ()   
  12.    
  13. @end   
  14.    
  15. @implementation ViewController   
  16.    
  17. -(void)downloadImage:(NSString *) url   
  18.     NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];   
  19.     UIImage *image = [[UIImage alloc]initWithData:data];   
  20.     if(image == nil)   
  21.            
  22.     else   
  23.         [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];   
  24.        
  25.    
  26.    
  27. -(void)updateUI:(UIImage*) image   
  28.     self.imageView.image = image;   
  29.    
  30.    
  31.    
  32. - (void)viewDidLoad   
  33.    
  34.     [super viewDidLoad];   
  35.        
  36. //    [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL];   
  37.     NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downloadImage:) object:kURL];   
  38.     [thread start];   
  39.    
  40.    
  41. - (void)didReceiveMemoryWarning   
  42.    
  43.     [super didReceiveMemoryWarning];   
  44.     // Dispose of any resources that can be recreated.   
  45.    
  46.    
  47. @end   
  线程间通讯 线程下载完图片后怎么通知主线程更新界面呢?
       
  1. [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES]; 
  performSelectorOnMainThread是NSObject的方法,除了可以更新主线程的数据外,还可以更新其他线程的比如:
       
  1. performSelector:onThread:withObject:waitUntilDone:  
  运行下载图片:   线程同步 我们演示一个经典的卖票的例子来讲NSThread的线程同步: 
       
  1. #import <UIKit/UIKit.h>   
  2.    
  3. @class ViewController;   
  4.    
  5. @interface AppDelegate : UIResponder <UIApplicationDelegate>   
  6.    
  7.     int tickets;   
  8.     int count;   
  9.     NSThread* ticketsThreadone;   
  10.     NSThread* ticketsThreadtwo;   
  11.     NSCondition* ticketsCondition;   
  12.     NSLock *theLock;   
  13.    
  14. @property (strong, nonatomic) UIWindow *window;   
  15.    
  16. @property (strong, nonatomic) ViewController *viewController;   
  17.    
  18. @end   
  
       
  1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions   
  2.    
  3.        
  4.     tickets = 100;   
  5.     count = 0;   
  6.     theLock = [[NSLock alloc] init];   
  7.     // 锁对象   
  8.     ticketsCondition = [[NSCondition alloc] init];   
  9.     ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];   
  10.     [ticketsThreadone setName:@"Thread-1"];   
  11.     [ticketsThreadone start];   
  12.        
  13.        
  14.     ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];   
  15.     [ticketsThreadtwo setName:@"Thread-2"];   
  16.     [ticketsThreadtwo start];   
  17.        
  18.     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];   
  19.     // Override point for customization after application launch.   
  20.     self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];   
  21.     self.window.rootViewController = self.viewController;   
  22.     [self.window makeKeyAndVisible];   
  23.     return YES;   
  24.    
  25.    
  26. - (void)run   
  27.     while (TRUE)    
  28.         // 上锁   
  29. //        [ticketsCondition lock];   
  30.         [theLock lock];   
  31.         if(tickets >= 0)   
  32.             [NSThread sleepForTimeInterval:0.09];   
  33.             count = 100 - tickets;   
  34.             NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThread currentThread] name]);   
  35.             tickets--;   
  36.         else   
  37.             break;   
  38.            
  39.         [theLock unlock];   
  40. //        [ticketsCondition unlock];   
  41.        
  42.    
 如果没有线程同步的lock,卖票数可能是-1.加上lock之后线程同步保证了数据的正确性。   上面例子我使用了两种锁,一种NSCondition ,一种是:NSLock。 NSCondition我已经注释了。   线程的顺序执行 他们都可以通过[ticketsCondition signal]; 发送信号的方式,在一个线程唤醒另外一个线程的等待。   比如: 
       
  1. #import "AppDelegate.h"   
  2.    
  3. #import "ViewController.h"   
  4.    
  5. @implementation AppDelegate   
  6.    
  7. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions   
  8.    
  9.        
  10.     tickets = 100;   
  11.     count = 0;   
  12.     theLock = [[NSLock alloc] init];   
  13.     // 锁对象   
  14.     ticketsCondition = [[NSCondition alloc] init];   
  15.     ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];   
  16.     [ticketsThreadone setName:@"Thread-1"];   
  17.     [ticketsThreadone start];   
  18.        
  19.     ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];   
  20.     [ticketsThreadtwo setName:@"Thread-2"];   
  21.     [ticketsThreadtwo start];   
  22.        
  23.     NSThread *ticketsThreadthree = [[NSThread alloc] initWithTarget:self selector:@selector(run3) object:nil];   
  24.     [ticketsThreadthree setName:@"Thread-3"];   
  25.     [ticketsThreadthree start];       
  26.     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];   
  27.     // Override point for customization after application launch.   
  28.     self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];   
  29.     self.window.rootViewController = self.viewController;   
  30.   

    以上是关于多线程之NSThreadCocoa NSOperationGCD的主要内容,如果未能解决你的问题,请参考以下文章

    并发编程之多线程

    python 之 多线程

    iOS底层探索之多线程(十五)—@synchronized源码分析

    多线程之pthread, NSThread, NSOperation, GCD

    编程思想之多线程与多进程——Java中的多线程

    iOS多线程之GCD小记