IOS多线程处理
在Object-c中,常用的多线程处理类分别为NSThread和NSOperationQueue。使用这两个类处理多线程,让复杂的多线程处理变得简单高效。下面分别介绍。
一、NSThread类
苹果公司的Cocoa框架共支持三种多线程机制,分别为NSThread、GCD(Grand Central Dispatch)、Cocoa NSOperatio。NSThree是官方推荐的线程处理方式,它在处理机制上,需要开发者负责手动管理Thread的生命周期,包括子线程与主线程之间的同步等。线程共享同一应用程序的部分内存空间,它们拥有对数据相同的访问权限。你得协调多个线程 对同一数据的访问,一般做法是在访问之前加锁,这会导致一定的性能开销。在 iOS 中我们可以使用多种形式的 thread。初次接触的读者也许会觉得生涩,但事实上NSThread类已经提供了完善的接口,在使用方式上并不会太难。使用NSTread管理线程,主要的步骤如下。
1)声明一个NSCondition同步锁;
2)声明若干个NSThread子线程;
3)指定NSThread子线程的目标指行方法(可以在构造函数中指定);
4)设置子线程的名称;
5)star启动子线程。
其中,子线程的执行方法一般只需要一个共同方法即可(可以通过线程名,分辨当前的执行线程)。下面通过代码演示NSThread类的使用。假设我们需要下载网络图片,在非异步形式的情况下,IOS界面必须等到图片下载完毕后,UI才会反应。这时利用多线程就可以达到异步下载的效果。
ViewController1.h
1
2
3
4
5
6
7
|
#import <UIKit/UIKit.h>
@interface ViewController1 : UIViewController{
NSCondition *_condition;
NSThread *_thread_1;
NSThread *_thread_2;
}
@end
|
ViewController1.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
//
// ViewController1.m
// Thread_demo
//
// Created by MAC on 13-4-22.
// Copyright (c) 2013年 李开涌. All rights reserved.
//
#import "ViewController1.h"
@interface ViewController1 ()
@end
@implementation ViewController1
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if
(self) {
// Custom initialization
self.title=@
"多线程NSThread"
;
}
return
self;
}
- (
void
)viewDidLoad
{
[super viewDidLoad];
//创建一个进程锁,实现线程同步
_condition=[[NSCondition alloc] init];
//创建线程1
_thread_1=[[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil];
[_thread_1 setName:@
"thread_1"
];
[_thread_1 start];
//创建线程2
_thread_2=[[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil];
[_thread_2 setName:@
"thread_2"
];
[_thread_2 start];
}
#pragma mark--线程执行方法
-(
void
)run{
//进程上锁
[_condition lock];
NSLog(@
"运行的线程名:%@"
,[[NSThread currentThread]name]);
if
([[[NSThread currentThread]name] isEqualToString:@
"thread_1"
]) {
NSLog(@
"111"
);
NSURL *imageUrl_1=[NSURL URLWithString:@
"http://t.beauty-soft.net/upload/ceiba20130224_014522_8679.jpg"
];
NSData *data_1=[NSData dataWithContentsOfURL:imageUrl_1];
UIImage *image_1=[UIImage imageWithData:data_1];
UIImageView *imageView_1=[[UIImageView alloc] initWithImage:image_1];
imageView_1.frame=CGRectMake(60, 20, 200, 200);
[self.view addSubview:imageView_1];
[imageView_1 release];
}
else
if
([[[NSThread currentThread]name] isEqualToString:@
"thread_2"
]){
NSLog(@
"222"
);
NSURL *imageUrl_2=[NSURL URLWithString:@
"http://t.beauty-soft.net/upload/ceiba20120704_121437_3455.jpg"
];
NSData *data_2=[NSData dataWithContentsOfURL:imageUrl_2];
UIImage *image_2=[UIImage imageWithData:data_2];
UIImageView *imageView_2=[[UIImageView alloc] initWithImage:image_2];
imageView_2.frame=CGRectMake(60, 250, 200, 200);
[self.view addSubview:imageView_2];
[imageView_2 release];
}
//解锁
[_condition unlock];
}
-(
void
)dealloc{
[_thread_1 release];
[_thread_2 release];
[_condition release];
[super dealloc];
}
- (
void
)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
|
二、NSOperationQueue类
如果需要让线程同时并行运行多个,可以将线程加入队列(Queue)中,NSOperationQueue类就是一个线程队列管理类,他提供了线程并行、队列的管理。可以认为NSOperationQueue就是一个线程管理器,通过addOperations方法,我们可以一次性把多个(数组形式)线程添加到队列中。同时,NSOperationQueue允许通过setMaxConcurrentOperationCount方法设置队列的并行(同一时间)运行数量。NSOperationQueue的使用步骤如下。
1)声明一个NSOperationQueue对象;
2)声明若干个NSInvocationOperation子线程对象,并指定回调方法;
3)将NSInvocationOperation子线程添加到数组;
4)把数组赋给NSOperationQueue类中的addOperations方法;
5) 实现回调方法;
6)在回调方法中实现performSelectorOnMainThread方法,更新主线程上的界面UI元素。
下面,使用NSOperationQueue类,实现前面NSThread类相同的功能(即下载图片)。代码如下。
ViewController2.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
//
// ViewController2.m
// Thread_demo
//
// Created by MAC on 13-4-22.
// Copyright (c) 2013年 李开涌. All rights reserved.
//
#import "ViewController2.h"
@interface ViewController2 ()
@end
@implementation ViewController2
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if
(self) {
// Custom initialization
self.title=@
"线程队列"
;
}
return
self;
}
- (
void
)viewDidLoad
{
[super viewDidLoad];
// 线程队列管理器,实现线程并行运行
_opeartionQueue=[[NSOperationQueue alloc] init];
//队列最大同时运行数量
[_opeartionQueue setMaxConcurrentOperationCount:1];
tags=20;
//创建线程1
NSInvocationOperation *invocationOpearation_1=[[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run:) object:@
"http://t.beauty-soft.net/upload/ceiba20130224_014522_8679.jpg"
] autorelease];
//创建线程2
NSInvocationOperation *invocationOpearation_2=[[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run:) object:@
"http://t.beauty-soft.net/upload/ceiba20120704_121437_3455.jpg"
] autorelease];
NSArray *array=@[invocationOpearation_1,invocationOpearation_2];
//把程序添加到管理器中
[_opeartionQueue addOperations:array waitUntilFinished:YES];
}
-(
void
)run:(NSString *)imageStrinUrl{
NSLog(@
"%@"
,[_opeartionQueue operations]);
NSLog(@
"mainQueue%@"
,[NSOperationQueue mainQueue]);
NSLog(@
"i==%i"
,tags);
NSLog(@
"urlStr:%@"
,imageStrinUrl);
NSURL *url=[NSURL URLWithString:imageStrinUrl];
NSData *data=[NSData dataWithContentsOfURL:url];
UIImage *image=[UIImage imageWithData:data];
UIImageView *imageView=[[[UIImageView alloc] initWithImage:image]autorelease];
imageView.frame=CGRectMake(60, tags, 200, 200);
tags+=200;
//通知主线程更新UI
[self performSelectorOnMainThread:@selector(updateUI:) withObject:imageView waitUntilDone:NO];
}
-(
void
)updateUI:(UIImageView *)imageView{
[self.view addSubview:imageView];
}
- (
void
)dealloc
{
[_opeartionQueue release];
[super dealloc];
}
- (
void
)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
|
[self performSelectorOnMainThr