(IOS)多线程开发

一、线程的使用

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

-(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 = 1;  // 设置队列同时执行线程最大数
[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 (1) 
    {
        [lock lock];   // 对可能出现互斥的变量设置部分进行锁定
        if (count>0) 
        {
            count = 100 - 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];来停止退出线程。

原文地址:https://www.cnblogs.com/mingfung-liu/p/3408243.html