(IOS)多线程开发

时间:2024-04-11 18:35:11

一、线程的使用

以向网络请求一张图片为例

-(void)downURL:(NSURL *)aURL
{
NSData *d = [NSData dataWithContentsOfURL:aURL];
UIImage *img = [UIImage imageWithData:d];
//imgView.image = img;
// 切换回主线程执行UI的操作
[imgView performSelectorOnMainThread:@selector(setImage:) withObject:img waitUntilDone:NO];
}

方法1:系统后台执行

[self performSelectorInBackground:@selector(downURL:) withObject:url];

方法2:利用C级的NSThread执行

[NSThread detachNewThreadSelector:@selector(downURL:) toTarget:self withObject:url];    // 分派线程执行一个方法,静态方法创建了线程,并开始执行

NSThread *t1 = [[NSThread alloc] initWithTarget:self selector:@selector(downURL:) object:url];
[t1 start]; // 创建具体线程对象需要触发开始

方法3:利用OC级的NSOperation执行,此处使用的是NSOperation的子类NSInvocationOperation(或NSBlockOperation)去执行,因为NSOperation只是一个抽象类,不能直接实例化使用

NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downURL:) object:url];
[op1 setQueuePriority:NSOperationQueuePriorityNormal]
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downURL:) object:url];
//[op1 start]; // 线程对象不放到队列中的话需要触发开始 queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = ; // 设置队列同时执行线程最大数
[queue addOperation:op1]; // 队列会自动打开线程
[queue addOperation:op2];
[op1 release];
[op2 release];

方法4:继承NSOperation自定义线程类,利用target-action机制

-(void)someMethod
{
BIDImageOperation *op = [[BIDImageOperation alloc] initWithTarget:self Selector:@selector(refreshUI:) URL:url1];
[op start];
// [op release];
} -(void)refreshUI:(UIImage *)aImg
{
[imgView performSelectorOnMainThread:@selector(setImage:) withObject:aImg waitUntilDone:NO];
}

using

#import <Foundation/Foundation.h>

@interface BIDImageOperation : NSOperation
{
NSString *_imgURL;
id _target;
SEL _action;
} @property (nonatomic,retain) NSString *imgURL;
@property (nonatomic,assign) id target;
@property (nonatomic,assign) SEL action; -(id)initWithTarget:(id)aTarget Selector:(SEL)aSelector URL:(NSString *)aURL; @end ###################################### #import "BIDImageOperation.h" @implementation BIDImageOperation
@synthesize imgURL = _imgURL,target = _target,action = _action; -(id)initWithTarget:(id)aTarget Selector:(SEL)aSelector URL:(NSString *)aURL
{
if (self = [super init]) {
self.imgURL = aURL;
self.target = aTarget;
self.action = aSelector;
}
return self;
} -(void)main
{
if ([self isCancelled]) {
return;
} NSURL *url = [NSURL URLWithString:self.imgURL];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [UIImage imageWithData:data]; if ([self isCancelled]) {
return;
} [self.target performSelector:self.action withObject:img];
} @end

custom thread

二、线程安全

以一个售票服务的程序为例

1.锁

-(void)someMethod
{
NSThread *t1 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
t1.name = @"window1";
[t1 start]; NSThread *t2 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
t2.name = @"window2";
[t2 start];
//[NSThread detachNewThreadSelector:@selector(saleTicket) toTarget:self withObject:nil];
} -(void)saleTicket
{
while ()
{
[lock lock]; // 对可能出现互斥的变量设置部分进行锁定
if (count>)
{
count = - ticket;
NSLog(@"%@ 卖出:%d 剩余:%d",[NSThread currentThread].name,ticket,count);
ticket++;
} else {
[lock unlock];
break;
}
[lock unlock];
}
}

2.取消

[op cancel];并不能将线程取消掉,因为该方法是建议关闭而已,除非线程里的main或调用的方法中有对这个建议做接受处理,如下

if ([self isCancelled]) // or  if([op isCancelled])
{
return;
}

在dealloc方法中,自定义线程类的成员变量都应该添加[op cancel];,队列则需要添加[queue cancelAllOperations];来停止退出线程。