IOS 多线程编程之NSOperationQueue

本文详细介绍了如何使用Objective-C中的NSOperationQueue进行并发处理与多任务队列操作,包括设置最大并发任务数、添加单个任务、批量任务及使用block语法任务,并通过实例展示了在不同场景下(如更新进度条、图片下载)的应用,以及如何封装代码以提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

创建任务队列
_opQueue=[[NSOperationQueue alloc]init];
设置同时执行任务的个数
[_opQueue setMaxConcurrentOperationCount:3];

添加一条任务
NSInvocationOperation*opt01=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(updateP1) object:nil];

将任务一添加到任务队列中
[_opQueue addOperation:opt01];
添加多条任务

NSMutableArray *arrayOp=[[NSMutableArray alloc]initWithCapacity:0];

for (int i=0; i<3; i++)
{
    //创建三个任务
    //3个对象来执行同一个函数
    //需要三个线程来分别执行这个函数
    NSInvocationOperation*op=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(updateArray) object:nil];

    [arrayOp addObject:op];
}
    //将任务数组添加到任务队列中,及时添加队列,不需要等待
[_opQueue addOperations:arrayOp waitUntilFinished:NO];

//添加一个block语法任务
[_opQueue addOperationWithBlock:^{

    int i=0;
    while (true)
    {
        i++;
        NSLog(@"i=%d",i);
        if (i>1000)
        {
            break;
        }
    }
}];

应用举例 1.
如何多并发的处理十条任务,比如用三个并发的任务处理 10个进度条?

- (void)viewDidLoad {
    [super viewDidLoad];
    _arrayProgress = [[NSMutableArray alloc] init];

    for (int i = 0 ; i < 10; i++){
    UIProgressView *pView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
        pView.frame = CGRectMake(10, 40+i*40, 300, 40);
        pView.progress = 0 ;
        [_arrayProgress addObject:pView];
        [self.view addSubview:pView];
        pView.tag = 101+i;
    }

    //创建任务队列(线程池)
    _opQueue = [[NSOperationQueue alloc] init];
        //设置同时可以执行的任务的个数
    [_opQueue setMaxConcurrentOperationCount:3];
    int max = (int)_opQueue.maxConcurrentOperationCount;
    NSLog(@"max = %d",max);
    _lock = [[NSLock alloc]init];

}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    NSInvocationOperation *op01 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(updateProgress01) object:nil];
    [_opQueue addOperation:op01];

    NSInvocationOperation *op02 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(updateProgress02) object:nil];
    [_opQueue addOperation:op02];

    NSInvocationOperation *op03 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(updateProgress03) object:nil];
    [_opQueue addOperation:op03];

    _cnt = 0;
    _cnt01 = 1;
    _cnt02 = 1;
    _cnt03 = 1;
}

- (void)updateProgress01 {

    while (_cnt < 11) {
        [_lock lock];
        _cnt++;
        _cnt01 = _cnt;
        [_lock unlock];

    while (_curProgress01 <= 1){
        NSLog(@"%f",_curProgress01);
        _curProgress01 += 0.0005;
        NSThread *mainT = [NSThread mainThread];
        [self performSelector:@selector(changeThread) onThread:mainT withObject:nil waitUntilDone:YES];
       }
        _curProgress01 = 0;
    }

}
- (void)changeThread {
    UIProgressView *pView = (UIProgressView *)[self.view viewWithTag:100+_cnt01];
    pView.progress = _curProgress01;
}

- (void)updateProgress02 {

    while (_cnt < 11) {
        [_lock lock];
        _cnt ++;
        _cnt02 = _cnt;
        [_lock unlock];
    while (_curProgress02 <= 1) {
        _curProgress02 += 0.00005;

        NSThread *mainT = [NSThread mainThread];

        [self performSelector:@selector(changeThread02) onThread:mainT withObject:nil waitUntilDone:YES];

       }
        _curProgress02 = 0;
    }
}
- (void)changeThread02 {
    UIProgressView *pView = (UIProgressView *)[self.view viewWithTag:100+_cnt02];
    pView.progress = _curProgress02;
}


- (void)updateProgress03 {
    while (_cnt < 11) {
        [_lock lock];
        _cnt ++;
        _cnt03 = _cnt;
        [_lock unlock];

    while (_curProgress03 <= 1) {
        _curProgress03 += 0.00005;
        NSThread *mainT = [NSThread mainThread];
        [self performSelector:@selector(changeThread03) onThread:mainT withObject:nil waitUntilDone:YES];

         }
        _curProgress03 = 0;
    }
}
- (void)changeThread03 {
    UIProgressView *pView = (UIProgressView *)[self.view viewWithTag:100+_cnt03];
    pView.progress = _curProgress03;
}

应用举例2
并发处理十张图片的下载,没点击一次,增加一条任务,处理下载图片,最大并发数为10 ,如果一直在点击的话,最多同时处理10条任务,但是任务队列就不止10条,点击多少次,则执行了多少次.

@implementation FKViewController
NSOperationQueue* queue;
- (void)viewDidLoad
{
    [super viewDidLoad];
    queue = [[NSOperationQueue alloc]init];
    // 设置该队列最多支持10条并发线程
    queue.maxConcurrentOperationCount = 10;
}
- (IBAction)clicked:(id)sender
{
    NSString* url = @"http://www.crazyit.org/logo.jpg";
    // 以self的downloadImageFromURL:方法作为执行体,创建NSOperation
    NSInvocationOperation* operation = [[NSInvocationOperation alloc]
        initWithTarget:self selector:@selector(downloadImageFromURL:)
        object:url];
    // 将NSOperation添加给NSOperationQueue
    [queue addOperation:operation];
}

// 定义一个方法作为线程执行体。
-(void)downloadImageFromURL:(NSString *) url
{
    // 从网络获取数据
    NSData *data = [[NSData alloc]
        initWithContentsOfURL:[NSURL URLWithString:url]];
    // 将网络数据初始化为UIImage对象
    UIImage *image = [[UIImage alloc]initWithData:data];
    if(image != nil)
    {
        // 在主线程中执行updateUI:方法
        [self performSelectorOnMainThread:@selector(updateUI:)
            withObject:image waitUntilDone:YES];
    }
    else
    {
        NSLog(@"---下载图片出现错误---");
    }
}
-(void)updateUI:(UIImage*) image
{
    self.iv.image = image;
}
@end

封装一下

@implementation FKViewController
NSOperationQueue* queue;
- (void)viewDidLoad
{
    [super viewDidLoad];
    queue = [[NSOperationQueue alloc]init];
    // 设置该队列最多支持10条并发线程
    queue.maxConcurrentOperationCount = 10;
}
- (IBAction)clicked:(id)sender
{
    // 定义要加载的图片的URL
    NSURL* url = [NSURL URLWithString:@"http://www.crazyit.org/logo.jpg"];
    // 创建FKDownImageOperation对象
    FKDownImageOperation* operation = [[FKDownImageOperation alloc]
        initWithURL:url imageView:self.iv];
    // 将NSOperation的子类的实例提交给NSOperationQueue
    [queue addOperation:operation];
}
@implementation FKDownImageOperation
- (id)initWithURL:(NSURL*)url imageView:(UIImageView*)iv
{
    self = [super init];
    if (self) {
        _imageView = iv;
        _url = url;
    }
    return self;
}
// 重写main方法,该方法将作为线程执行体
- (void)main
{   
    // 从网络获取数据
    NSData *data = [[NSData alloc]
        initWithContentsOfURL:self.url];
    // 将网络数据初始化为UIImage对象
    UIImage *image = [[UIImage alloc]initWithData:data];
    if(image != nil)
    {
        // 在主线程中执行updateUI:方法
        [self performSelectorOnMainThread:@selector(updateUI:)
            withObject:image waitUntilDone:YES]; // ①
    }
    else
    {
        NSLog(@"---下载图片出现错误---");
    }
}
-(void)updateUI:(UIImage*) image
{
    self.imageView.image = image;
}

利用[NSBlockOperation
blockOperationWithBlock:^{}
]让代码更加紧凑



@implementation FKViewController
NSOperationQueue* queue;
- (void)viewDidLoad
{
    [super viewDidLoad];
    queue = [[NSOperationQueue alloc]init];
    // 设置该队列最多支持10条并发线程
    queue.maxConcurrentOperationCount = 10;
}
- (IBAction)clicked:(id)sender
{
    NSString* url = @"http://www.crazyit.org/logo.jpg";
    // 以传入的代码块作为执行体,创建NSOperation
    NSBlockOperation* operation = [NSBlockOperation
        blockOperationWithBlock:^{
            // 从网络获取数据
            NSData *data = [[NSData alloc]
                initWithContentsOfURL:[NSURL URLWithString:url]];
            // 将网络数据初始化为UIImage对象
            UIImage *image = [[UIImage alloc]initWithData:data];
            if(image != nil)
            {
                // 在主线程中执行updateUI:方法
                [self performSelectorOnMainThread:@selector(updateUI:)
                    withObject:image waitUntilDone:YES];
            }
            else
            {
                NSLog(@"---下载图片出现错误---");
            }
        }];
    // 将NSOperation添加给NSOperationQueue
    [queue addOperation:operation];
}
-(void)updateUI:(UIImage*) image
{
    self.iv.image = image;
}
<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值