一、简介:
1.1 iOS有三种多线程编程的技术,分别是:
1.、NSThread html
二、Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue的使用) ios
三、GCD 全称:Grand Central Dispatch( iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用) 编程
这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的。 多线程
这篇咱们主要介绍和使用NSThread,后面会继续二、3 的讲解和使用。 app
1.2 三种方式的有缺点介绍:
NSThread: 分布式
优势:NSThread 比其余两个轻量级 ide
缺点:须要本身管理线程的生命周期,线程同步。线程同步对数据的加锁会有必定的系统开销 学习
NSThread实现的技术有下面三种: flex
Technology ui |
Description |
Cocoa threads |
Cocoa implements threads using the NSThread class. Cocoa also provides methods on NSObject for spawning new threads and executing code on already-running threads. For more information, see “Using NSThread” and “Using NSObject to Spawn a Thread.” |
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. For more information, see “Using POSIX 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 NSThread class or POSIX threads. If you need more information on this technology, see Multiprocessing Services Programming Guide. |
通常使用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的使用。
二、NSThread的使用
2.1 NSThread 有两种直接建立方式:
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
第一个是实例方法,第二个是类方法
- 一、[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];
- 二、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:@"Thread-2"];
- [ticketsThreadtwo start];
-
- self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
- // Override point for customization after application launch.
- self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
- self.window.rootViewController = self.viewController;
- [self.window makeKeyAndVisible];
- return YES;
- }
-
- - (void)run{
- while (TRUE) {
- // 上锁
- // [ticketsCondition lock];
- [theLock lock];
- if(tickets >= 0){
- [NSThread sleepForTimeInterval:0.09];
- count = 100 - tickets;
- NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThread currentThread] name]);
- tickets--;
- }else{
- break;
- }
- [theLock unlock];
- // [ticketsCondition unlock];
- }
- }
若是没有线程同步的lock,卖票数多是-1.加上lock以后线程同步保证了数据的正确性。
上面例子我使用了两种锁,一种NSCondition ,一种是:NSLock。 NSCondition我已经注释了。
线程的顺序执行
他们均可以经过
[ticketsCondition signal]; 发送信号的方式,在一个线程唤醒另一个线程的等待。
好比:
- #import "AppDelegate.h"
-
- #import "ViewController.h"
-
- @implementation AppDelegate
-
- - (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:@"Thread-2"];
- [ticketsThreadtwo start];
-
- NSThread *ticketsThreadthree = [[NSThread alloc] initWithTarget:self selector:@selector(run3) object:nil];
- [ticketsThreadthree setName:@"Thread-3"];
- [ticketsThreadthree start];
- self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
- // Override point for customization after application launch.
- self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
- self.window.rootViewController = self.viewController;
- [self.window makeKeyAndVisible];
- return YES;
- }
-
- -(void)run3{
- while (YES) {
- [ticketsCondition lock];
- [NSThread sleepForTimeInterval:3];
- [ticketsCondition signal];
- [ticketsCondition unlock];
- }
- }
-
- - (void)run{
- while (TRUE) {
- // 上锁
- [ticketsCondition lock];
- [ticketsCondition wait];
- [theLock lock];
- if(tickets >= 0){
- [NSThread sleepForTimeInterval:0.09];
- count = 100 - tickets;
- NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThread currentThread] name]);
- tickets--;
- }else{
- break;
- }
- [theLock unlock];
- [ticketsCondition unlock];
- }
- }
wait是等待,我加了一个 线程3 去唤醒其余两个线程锁中的wait
其余同步
咱们可使用指令 @synchronized 来简化 NSLock的使用,这样咱们就没必要显示编写建立NSLock,加锁并解锁相关代码。
- (void)doSomeThing:(id)anObj
{
@synchronized(anObj)
{
// Everything between the braces is protected by the @synchronized directive.
}
}
还有其余的一些锁对象,好比:循环锁NSRecursiveLock,条件锁NSConditionLock,分布式锁NSDistributedLock等等,能够本身看官方文档学习
NSThread下载图片的例子代码:http://download.csdn.net/detail/totogo2010/4591149