您的位置:首页 > 移动开发 > Objective-C

iphone 线程总结— detachNewThreadSelector的使用

2013-10-21 18:08 423 查看
不管是iphone中还是其他的操作系统,多线程在各种编程语言中都是难点,很多语言中实现起来很麻烦,objective-c虽然源于c,但其多线程编程却相当简单,可以与java相媲美。多线程编程是防止主线程堵塞,增加运行效率等等的最佳方法。而原始的多线程方法存在很多的毛病,包括线程锁死等。

一、线程创建与启动

线程创建主要有二种方式:

(id)init;//designatedinitializer
(id)initWithTarget:(id)targetselector:
(SEL)selectorobject:(id)argument;


当然,还有一种比较特殊,就是使用所谓的convenientmethod,这个方法可以直接生成一个线程并启动它,而且无需为线程的清理负责。这个方法的接口是:
(void)detachNewThreadSelector:
(SEL)aSelectortoTarget:
(id)aTargetwithObject:
(id)anArgument


前两种方法创建后,需要手机启动,启动的方法是:
(void)start;


二、线程的同步与锁

要说明线程的同步与锁,最好的例子可能就是多个窗口同时售票的售票系统了。我们知道在java中,使用synchronized来同步,而iphone虽然没有提供类似java下的synchronized关键字,但提供了NSCondition对象接口。查看NSCondition的接口说明可以看出,NSCondition是iphone下的锁对象,所以我们可以使用NSCondition实现iphone中的线程安全。这是来源于网上的一个例子:

SellTicketsAppDelegate.h文件
//SellTicketsAppDelegate.h
import<UIKit/UIKit.h>
@interfaceSellTicketsAppDelegate:NSObject<UIApplicationDelegate>{
inttickets;
intcount;
NSThread*ticketsThreadone;
NSThread*ticketsThreadtwo;
NSCondition*ticketsCondition;
UIWindow*window;
}
@property(nonatomic,retain)IBOutletUIWindow*window;
@end
SellTicketsAppDelegate.m文件
//SellTicketsAppDelegate.m
import"SellTicketsAppDelegate.h"
@implementationSellTicketsAppDelegate
@synthesizewindow;
-(void)applicationDidFinishLaunching:(UIApplication*)application{
tickets=100;
count=0;
//锁对象
ticketCondition=[[NSConditionalloc]init];
ticketsThreadone=[[NSThreadalloc]initWithTarget:selfselector:@selector(run)object:nil];
[ticketsThreadonesetName:@"Thread-1"];
[ticketsThreadonestart];
ticketsThreadtwo=[[NSThreadalloc]initWithTarget:selfselector:@selector(run)object:nil];
[ticketsThreadtwosetName:@"Thread-2"];
[ticketsThreadtwostart];
//[NSThreaddetachNewThreadSelector:@selector(run)toTarget:selfwithObject:nil];
//Overridepointforcustomizationafterapplicationlaunch
[windowmakeKeyAndVisible];

}

-(void)run{
while(TRUE){
//上锁
[ticketsConditionlock];
if(tickets>0){
[NSThreadsleepForTimeInterval:0.5];
count=100-tickets;
NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThreadcurrentThread]name]);
tickets--;
}else{
break;
}
[ticketsConditionunlock];
}
}
-(void)dealloc{
[ticketsThreadonerelease];
[ticketsThreadtworelease];
[ticketsConditionrelease];
[windowrelease];
[superdealloc];
}
@end


三、线程的交互

线程在运行过程中,可能需要与其它线程进行通信,如在主线程中修改界面等等,可以使用如下接口:
(void)performSelectorOnMainThread:
(SEL)aSelectorwithObject:
(id)argwaitUntilDone:
(BOOL)wait


由于在本过程中,可能需要释放一些资源,则需要使用NSAutoreleasePool来进行管理,如:

(void)startTheBackgroundJob{
NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];
//todosomethinginyourthreadjob
...
[selfperformSelectorOnMainThread:@selector(makeMyProgressBarMoving)withObject:nilwaitUntilDone:NO];
[poolrelease];
}

举例说明怎么简单的创建一个子线程。用到的类是NSThread类,这里使用detachNewTheadSelector:toTagaet:withObject创建一个线程。函数setupThread:(NSArray*)userInfor。通过userInfor将需要的数据传到线程中。函数定义:

[代码]c#/cpp/oc代码:

[code]01
-(
void
)setupThread:(NSArray*)userInfor{
02
03
[NSThread
detachNewThreadSelector:@selector(threadFunc:)toTarget:selfwithObject:(id)userInfor];
04
05
}
06
07
-
(
void
)threadFunc:(id)userInfor{
08
09
NSAutoreleasePool*pool
=[[NSAutoreleasePoolalloc]init];
10
11
//。。。。需要做的处理。
12
13
//这里线程结束后立即返回
14
15
[self
performSelectorOnMainThread:@selector(endThread)withObject:nilwaitUntilDone:NO];
16
17
[pool
release];
18
19
}
performSelectorOnMainThread通知主线程执行函数endThread。也可以使用performSelector:onThread:withObject:waitUntil通知某线程执行线程结束后的处理。线程内不要刷新界面。如果需要刷新界面,通过performSelectorOnMainThread,调出主线程中的方法去刷新。例如,启动一个线程下载图片://启动线程[NSThreaddetachNewThreadSelector:@selector(downloadImage:)toTarget:selfwithObject:url];//线程函数

[代码]c#/cpp/oc代码:

01
-
(
void
)
downloadImage:(NSString*)url{
02
03
_subThreed
=[NSThreadcurrentThread];
04
05
self.uploadPool
=[[NSAutoreleasePoolalloc]init];
06
self.characterBuffer
=[NSMutableDatadata];
07
done
=NO;
08
[[NSURLCache
sharedURLCache]removeAllCachedResponses];
09
10
NSMutableURLRequest
*theRequest=[NSMutableURLRequestrequestWithURL:[NSURLURLWithString:url]];
11
12
self.connection
=[[NSURLConnectionalloc]initWithRequest:theRequest
delegate
:self];
13
[self
performSelectorOnMainThread:@selector(httpConnectStart)withObject:nilwaitUntilDone:NO];
14
if
(connection
!=nil){
15
do
{
16
[[NSRunLoop
currentRunLoop]runMode:NSDefaultRunLoopModebeforeDate:[NSDatedistantFuture]];
17
}
while
(!done);
18
}
19
20
self.photo
=[UIImageimageWithData:characterBuffer];
21
22
23
//下载结束,刷新
24
[self
performSelectorOnMainThread:@selector(fillPhoto)withObject:nilwaitUntilDone:NO];
25
26
//
Releaseresourcesusedonlyinthisthread.
27
self.connection
=nil;
28
[uploadPool
release];
29
self.uploadPool
=nil;
30
31
_subThreed
=nil;
32
}
33
34
35
36
#pragma
markNSURLConnectionDelegatemethods
37
38
/*
39
Disable
cachingsothateachtimewerunthisappwearestartingwithacleanslate.Youmaynotwanttodothisinyourapplication.
40
*/
41
-
(NSCachedURLResponse*)connection:(NSURLConnection*)connectionwillCacheResponse:(NSCachedURLResponse*)cachedResponse{
42
43
return
nil;
44
}
45
46
//
Forwarderrorstothedelegate.
47
-
(
void
)connection:(NSURLConnection
*)connectiondidFailWithError:(NSError*)error{
48
done
=YES;
49
[self
performSelectorOnMainThread:@selector(httpConnectEnd)withObject:nilwaitUntilDone:NO];
50
[characterBuffer
setLength:0];
51
52
}
53
54
//
Calledwhenachunkofdatahasbeendownloaded.
55
-
(
void
)connection:(NSURLConnection
*)connectiondidReceiveData:(NSData*)data{
56
//
Processthedownloadedchunkofdata.
57
58
[characterBuffer
appendData:data];
59
60
}
61
62
-
(
void
)connectionDidFinishLoading:(NSURLConnection
*)connection{
63
64
[self
performSelectorOnMainThread:@selector(httpConnectEnd)withObject:nilwaitUntilDone:NO];
65
//
Settheconditionwhichendstherunloop.
66
done
=YES;
67
68
}
首先我们需要创建一个线程有两种方法:-(id)initWithTarget:(id)targetselector:(SEL)selectorobject:(id)argument+(void)detachNewThreadSelector:(SEL)aSelectortoTarget:(id)aTargetwithObject:(id)anArgument因为第二种方法不用对线程进行清理,所以我们常用第二种哦个方法。[NSThreaddetachNewThreadSelector:@selector(new:)toTarget:selfwithObject:nil];-(void)new:(id)sender{[_myConditionlock];//performSelectorInBackgroud主要进行逻辑上处理[selfperformSelectorInBackgroud:@selector(doInBackgroud:)withObject:nil];//perfomSelectorOnMainThread主要进行界面UI上的处理[selfperfomSelectorOnMainThread:@selector(doOnMain:)withObject:nil];//[NSThreadsleepForTimeInterval:n];[_myConditionsignal];[_myConditionunlock];[NSThreadexit];return;}
[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息