1、简介:
1.1 iOS有三种多线程编程的技术,分别是:
1.、NSThread
2、Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue的使用)
3、GCD 全称:Grand Central
Dispatch( iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用)
这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的。
这篇我们主要介绍和使用NSThread,后面会继续2、3 的讲解和使用。
1.2 三种方式的有缺点介绍:
NSThread:
优点:NSThread 比其他两个轻量级
缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销
NSThread实现的技术有下面三种:
Technology |
Description |
---|---|
Cocoa threads |
Cocoa implements threads using the |
POSIX threads |
POSIX threads provide a C-based interface for creating threads. If you are not writing a Cocoa application, this is the best choice for creating threads. The POSIX interface is relatively simple to use and offers ample flexibility for configuring your threads. |
Multiprocessing Services |
Multiprocessing Services is a legacy C-based interface used by applications transitioning from older versions of Mac OS. This technology is available in OS X only and should be avoided for any new development. Instead, you should use the |
一般使用cocoa thread 技术。
Cocoa operation
优点:不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上。
Cocoa operation 相关的类是 NSOperation ,NSOperationQueue。NSOperation是个抽象类,使用它必须用它的子类,可以实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。
GCD
Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。在iOS4.0开始之后才能使用。GCD是一个替代诸如NSThread, NSOperationQueue, NSInvocationOperation等技术的很高效和强大的技术。现在的iOS系统都升级到6了,所以不用担心该技术不能使用。
介绍完这三种多线程编程方式,我们这篇先介绍NSThread的使用。
2、NSThread的使用
2.1 NSThread 有两种直接创建方式:
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
第一个是实例方法,第二个是类方法
- 1、[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];
- 2、NSThread* myThread = [[NSThread alloc] initWithTarget:self
- selector:@selector(doSomething:)
- object:nil];
- [myThread start];
2.2参数的意义:
selector :线程执行的方法,这个selector只能有一个参数,而且不能有返回值。
target :selector消息发送的对象
argument:传输给target的唯一参数,也可以是nil
第一种方式会直接创建线程并且开始运行线程,第二种方式是先创建线程对象,然后再运行线程操作,在运行线程操作前可以设置线程的优先级等线程信息
2.3 PS:不显式创建线程的方法:
用NSObject的类方法 performSelectorInBackground:withObject: 创建一个线程:
[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];
2.4 下载图片的例子:
2.4.1 新建singeView app
新建项目,并在xib文件上放置一个imageView控件。按住control键拖到viewControll
er.h文件中创建imageView IBOutlet
ViewController.m中实现:
- //
- // ViewController.m
- // NSThreadDemo
- //
- // Created by rongfzh on 12-9-23.
- // Copyright (c) 2012年 rongfzh. All rights reserved.
- //
- #import "ViewController.h"
- #define kURL @"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"
- @interface ViewController ()
- @end
- @implementation ViewController
- -(void)downloadImage:(NSString *) url{
- NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
- UIImage *image = [[UIImage alloc]initWithData:data];
- if(image == nil){
- }else{
- [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
- }
- }
- -(void)updateUI:(UIImage*) image{
- self.imageView.image = image;
- }
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- // [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL];
- NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downloadImage:) object:kURL];
- [thread start];
- }
- - (void)didReceiveMemoryWarning
- {
- [super didReceiveMemoryWarning];
- // Dispose of any resources that can be recreated.
- }
- @end
2.4.2线程间通讯
线程下载完图片后怎么通知主线程更新界面呢?
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
performSelectorOnMainThread是NSObject的方法,除了可以更新主线程的数据外,还可以更新其他线程的比如:
用:performSelector:onThread:withObject:waitUntilDone:
运行下载图片:
图片下载下来了。
2.3 线程同步
我们演示一个经典的卖票的例子来讲NSThread的线程同步:
.h
- #import <UIKit/UIKit.h>
- @class ViewController;
- @interface AppDelegate : UIResponder <UIApplicationDelegate>
- {
- int tickets;
- int count;
- NSThread* ticketsThreadone;
- NSThread* ticketsThreadtwo;
- NSCondition* ticketsCondition;
- NSLock *theLock;
- }
- @property (strong, nonatomic) UIWindow *window;
- @property (strong, nonatomic) ViewController *viewController;
- @end
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- {
- tickets = 100;
- count = 0;
- theLock = [[NSLock alloc] init];
- // 锁对象
- ticketsCondition = [[NSCondition alloc] init];
- ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
- [ticketsThreadone setName:@"Thread-1"];
- [ticketsThreadone start];
- ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
- [ticketsThreadtwo setName:@