iphone 线程总结— detachNewThreadSelector的使用
来源:互联网 发布:淘宝小女孩布鞋 编辑:程序博客网 时间:2024/05/17 01:29
不管是iphone中还是其他的操作系统,多线程在各种编程语言中都是难点,很多语言中实现起来很麻烦,objective-c虽然源于c,但其多线程编程却相当简单,可以与java相媲美。多线程编程是防止主线程堵塞,增加运行效率等等的最佳方法。而原始的多线程方法存在很多的毛病,包括线程锁死等。
一、线程创建与启动
线程创建主要有二种方式:
- (id)init; // designated initializer
- (id)initWithTarget:(id)target selector:
- (SEL)selector object:(id)argument;
当然,还有一种比较特殊,就是使用所谓的convenient method,这个方法可以直接生成一个线程并启动它,而且无需为线程的清理负责。这个方法的接口是:
- (void)detachNewThreadSelector:
- (SEL)aSelector toTarget:
- (id)aTarget withObject:
- (id)anArgument
前两种方法创建后,需要手机启动,启动的方法是:
- (void)start;
二、线程的同步与锁
要说明线程的同步与锁,最好的例子可能就是多个窗口同时售票的售票系统了。我们知道在java中,使用synchronized来同步,而iphone虽然没有提供类似java下的synchronized关键字,但提供了NSCondition对象接口。查看NSCondition的接口说明可以看出,NSCondition是iphone下的锁对象,所以我们可以使用NSCondition实现iphone中的线程安全。这是来源于网上的一个例子:
SellTicketsAppDelegate.h 文件
- // SellTicketsAppDelegate.h
- import <UIKit/UIKit.h>
- @interface SellTicketsAppDelegate : NSObject <UIApplicationDelegate> {
- int tickets;
- int count;
- NSThread* ticketsThreadone;
- NSThread* ticketsThreadtwo;
- NSCondition* ticketsCondition;
- UIWindow *window;
- }
- @property (nonatomic, retain) IBOutlet UIWindow *window;
- @end
- SellTicketsAppDelegate.m 文件
- // SellTicketsAppDelegate.m
- import "SellTicketsAppDelegate.h"
- @implementation SellTicketsAppDelegate
- @synthesize window;
- - (void)applicationDidFinishLaunching:(UIApplication *)application {
- tickets = 100;
- count = 0;
- // 锁对象
- ticketCondition = [[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 detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
- // Override point for customization after application launch
- [window makeKeyAndVisible];
- }
- - (void)run{
- while (TRUE) {
- // 上锁
- [ticketsCondition lock];
- if(tickets > 0){
- [NSThread sleepForTimeInterval:0.5];
- count = 100 - tickets;
- NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThread currentThread] name]);
- tickets--;
- }else{
- break;
- }
- [ticketsCondition unlock];
- }
- }
- - (void)dealloc {
- [ticketsThreadone release];
- [ticketsThreadtwo release];
- [ticketsCondition release];
- [window release];
- [super dealloc];
- }
- @end
三、线程的交互
线程在运行过程中,可能需要与其它线程进行通信,如在主线程中修改界面等等,可以使用如下接口:
- (void)performSelectorOnMainThread:
- (SEL)aSelector withObject:
- (id)arg waitUntilDone:
- (BOOL)wait
由于在本过程中,可能需要释放一些资源,则需要使用NSAutoreleasePool来进行管理,如:
- (void)startTheBackgroundJob {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- // to do something in your thread job
- ...
- [self performSelectorOnMainThread:@selector(makeMyProgressBarMoving) withObject:nil waitUntilDone:NO];
- [pool release];
- }
举例说明怎么简单的创建一个子线程。
用到的类是NSThread类,这里使用detachNewTheadSelector:toTagaet:withObject创建一个线程。
函数setupThread:(NSArray*)userInfor。通过userInfor将需要的数据传到线程中。
函数定义:
[代码]c#/cpp/oc代码:
01
-(
void
)setupThread:(NSArray*)userInfor{
02
03
[NSThread detachNewThreadSelector:@selector(threadFunc:) toTarget:self withObject:(id)userInfor];
04
05
}
06
07
- (
void
)threadFunc:(id)userInfor{
08
09
NSAutoreleasePool*pool = [[NSAutoreleasePool alloc] init];
10
11
//。。。。需要做的处理。
12
13
//这里线程结束后立即返回
14
15
[self performSelectorOnMainThread:@selector(endThread) withObject:nil waitUntilDone:NO];
16
17
[pool release];
18
19
}
performSelectorOnMainThread通知主线程执行函数endThread。也可以使用performSelector:onThread:withObject:waitUntil 通知某线程执行线程结束后的处理。
线程内不要刷新界面。如果需要刷新界面,通过performSelectorOnMainThread,调出主线程中的方法去刷新。
例如,启动一个线程下载图片:
//启动线程
[NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:url];
//线程函数
[代码]c#/cpp/oc代码:
01
- (
void
) downloadImage:(NSString*)url{
02
03
_subThreed = [NSThread currentThread];
04
05
self.uploadPool = [[NSAutoreleasePool alloc] init];
06
self.characterBuffer = [NSMutableData data];
07
done = NO;
08
[[NSURLCache sharedURLCache] removeAllCachedResponses];
09
10
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURLURLWithString:url]];
11
12
self.connection = [[NSURLConnection alloc] initWithRequest:theRequest
delegate
:self];
13
[self performSelectorOnMainThread:@selector(httpConnectStart) withObject:nil waitUntilDone:NO];
14
if
(connection != nil) {
15
do
{
16
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
17
}
while
(!done);
18
}
19
20
self.photo = [UIImage imageWithData:characterBuffer];
21
22
23
//下载结束,刷新
24
[self performSelectorOnMainThread:@selector(fillPhoto) withObject:nil waitUntilDone:NO];
25
26
// Release resources used only in this thread.
27
self.connection = nil;
28
[uploadPool release];
29
self.uploadPool = nil;
30
31
_subThreed = nil;
32
}
33
34
35
36
#pragma mark NSURLConnection Delegate methods
37
38
/*
39
Disable caching so that each time we run this app we are starting with a clean slate. You may not want to do this in your application.
40
*/
41
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
42
43
return
nil;
44
}
45
46
// Forward errors to the delegate.
47
- (
void
)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
48
done = YES;
49
[self performSelectorOnMainThread:@selector(httpConnectEnd) withObject:nil waitUntilDone:NO];
50
[characterBuffer setLength:0];
51
52
}
53
54
// Called when a chunk of data has been downloaded.
55
- (
void
)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
56
// Process the downloaded chunk of data.
57
58
[characterBuffer appendData:data];
59
60
}
61
62
- (
void
)connectionDidFinishLoading:(NSURLConnection *)connection {
63
64
[self performSelectorOnMainThread:@selector(httpConnectEnd) withObject:nil waitUntilDone:NO];
65
// Set the condition which ends the run loop.
66
done = YES;
67
68
}
首先我们需要创建一个线程有两种方法:
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
因为第二种方法不用对线程进行清理,所以我们常用第二种哦个方法。
[NSThread detachNewThreadSelector:@selector(new:) toTarget:self withObject:nil];
- (void)new:(id)sender{
[_myCondition lock];
//performSelectorInBackgroud主要进行逻辑上处理
[self performSelectorInBackgroud:@selector(doInBackgroud:) withObject:nil];
//perfomSelectorOnMainThread主要进行界面UI上的处理
[self perfomSelectorOnMainThread:@selector(doOnMain:) withObject:nil];
//[NSThread sleepForTimeInterval:n];
[_myCondition signal];
[_myCondition unlock];
[NSThread exit];
return;
}
- iphone 线程总结— detachNewThreadSelector的使用
- iphone 线程总结— detachNewThreadSelector的使用
- iphone 线程总结— detachNewThreadSelector的使用
- iphone 线程总结— detachNewThreadSelector的使用
- iphone 线程总结— detachNewThreadSelector的使用
- iphone 线程总结— detachNewThreadSelector的使用
- iphone 线程总结— detachNewThreadSelector的使用
- IOS学习 performSelectorOnMainThread 和detachNewThreadSelector的使用
- iphone开发之线程的使用详解
- 线程的使用总结
- iphone开发第五课:performSelectorOnMainThread 和detachNewThreadSelector区别
- iPhone开发——AFN使用总结
- iphone SQLite3使用总结
- iphone线程中使用异步网络的悲催经历
- iphone线程中使用异步网络的悲催经历
- iphone线程中使用异步网络的悲催经历
- 《转》iphone线程中使用异步网络的…
- 线程状态,多线程的使用,线程的通信(总结)
- linux下端口扫描的实现(TCP connect、TCP SYN、TCP FIN、UDP四种方式)4 TCP SYN方式
- JQuery五:jQuery中.bind() .live() .delegate() .on()的区别
- 用phonegap+jquerymobile写天气预报(二)---初始化问题
- 坑爹的 xwiki 二次开发
- java socket实现多客户端群聊
- iphone 线程总结— detachNewThreadSelector的使用
- VC++6.0 GPS心得体会
- 《实用OpenCV》<二> 在你的电脑上配置OpenCV
- As的用法
- android中常用的弹出提示框
- PHP sprintf() 函数
- 养生保健,延年益寿---剖析互动能量杯的价值
- 功能链----责任链的变形
- 黑马程序员_类、接口