多线程开发是一件需要特别精心的事情,即使是对有多年开发经验的工程师来说。

为了能让初级开发工程师也能使用多线程,同时还要简化复杂性。各种编程工具提供了各自的办法。对于iOS来说,建议在尽可能的情况下避免直接操作线程,使用比如NSOperationQueue这样的机制。

可以把NSOperationQueue看作一个线程池,可往线程池中添加操作(NSOperation)到队列中。线程池中的线程可看作消费者,从队列中取走操作,并执行它。

你可以设置线程池中只有一个线程,这样,各个操作就可以认为是近似的顺序执行了。为什么说是近似呢,后面会做解释。

编写最简单的示例

先写个最简单的示例。

编写一个NSOperation的子类,只需实现main方法。这里非常类似Java的Thread,你可以继承它,并覆盖run方法,在该方法里面写入需要执行的代码。这里的main方法和run方法作用是相似的。

头文件:

@interface MyTask : NSOperation {
    int operationId;
}

@property int operationId;

@end

这里的operationId属性不是必须的,是我想在后面标识区分多个Task的标识位。

m文件:

@implementation MyTask

@synthesize operationId;

- (void)main{
    NSLog(@"task %i run … ",operationId);
    [NSThread sleepForTimeInterval:10];
    NSLog(@"task %i is finished. ",operationId);
}

@end

这里模拟了一个耗时10秒钟的操作。

下面需要把Task加入到队列中:

- (void)viewDidLoad {
    [super viewDidLoad];
    queue=[[NSOperationQueue alloc] init];
   
    int index=1;
    MyTask *task=[[[MyTask alloc] init] autorelease];
    task.operationId=index++;
        
    [queue addOperation:task];

我直接找了个Controller的方法写上了。运行结果是,界面出现了,而task还未执行完,说明是多线程的。10秒钟后,日志打印完毕,类似这样:

2011-07-18 15:59:14.622 MultiThreadTest[24271:6103] task 1 run …

2011-07-18 15:59:24.623 MultiThreadTest[24271:6103] task 1 is finished.

可以向操作队列(NSOperationQueue)增加多个操作,比如这样:

- (void)viewDidLoad {
    [super viewDidLoad];
    queue=[[NSOperationQueue alloc] init];
   
    int index=1;
    MyTask *task=[[[MyTask alloc] init] autorelease];
    task.operationId=index++;    
    [queue addOperation:task];
   
    task=[[[MyTask alloc] init] autorelease];
    task.operationId=index++;

[queue addOperation:task];
}

那么打印出的内容是不定的,有可能是这样:

2011-07-18 15:49:48.087 MultiThreadTest[24139:6203] task 1 run …

2011-07-18 15:49:48.087 MultiThreadTest[24139:1903] task 2 run …
2011-07-18 15:49:58.122 MultiThreadTest[24139:6203] task 1 is finished.
2011-07-18 15:49:58.122 MultiThreadTest[24139:1903] task 2 is finished.

甚至有可能是这样:

2011-07-18 15:52:24.686 MultiThreadTest[24168:1b03] task 2 run …

2011-07-18 15:52:24.685 MultiThreadTest[24168:6003] task 1 run …
2011-07-18 15:52:34.708 MultiThreadTest[24168:1b03] task 2 is finished.
2011-07-18 15:52:34.708 MultiThreadTest[24168:6003] task 1 is finished.

因为两个操作提交的时间间隔很近,线程池中的线程,谁先启动是不定的。

那么,如果需要严格意义的顺序执行,怎么办呢?

处理操作之间的依赖关系

如果操作直接有依赖关系,比如第二个操作必须等第一个操作结束后再执行,需要这样写:

queue=[[NSOperationQueue alloc] init];

int index=1;
MyTask *task=[[[MyTask alloc] init] autorelease];
task.operationId=index++;

[queue addOperation:task];

task=[[[MyTask alloc] init] autorelease];
task.operationId=index++;

if ([[queue operations] count]>0) {
    MyTask *theBeforeTask=[[queue operations] lastObject];
    [task addDependency:theBeforeTask];
}

[queue addOperation:task];

这样,即使是多线程情况下,可以看到操作是严格按照先后次序执行的。

控制线程池中的线程数

可以通过类似下面的代码:

[queue setMaxConcurrentOperationCount:2];

来设置线程池中的线程数,也就是并发操作数。默认情况下是-1,也就是没有限制,同时运行队列中的全部操作。

队列的优先级

使用NSOperationQueue简化多线程开发中介绍了iOS的操作队列使用方法。这里补充一下队列的优先级功能。

假设现在队列中有多个操作(NSOperation),现在再向队列中加入新的操作,并且希望新增加的操作排在未执行操作的最前面。这时就需要设置操作的优先级了。

编写了个最简单的NSOperation,头文件:

#import <Foundation/Foundation.h>

@interface MyOperation : NSOperation{
    NSString *name;
}

@property (nonatomic,retain) NSString *name;

@end

实现文件:

#import "MyOperation.h"

@implementation MyOperation

@synthesize name;

-(void) main{
    NSLog(@"run operation: %@",name);
    [NSThread sleepForTimeInterval:3];
}

@end

在控制器里创建3个实例:

- (void)viewDidLoad {
    [super viewDidLoad];
    queue=[[NSOperationQueue alloc] init];
    [queue setMaxConcurrentOperationCount:1];
   
    MyOperation *o1=[[[MyOperation alloc] init] autorelease];
    o1.name=@"o1";
    [queue addOperation:o1];
   
    MyOperation *o2=[[[MyOperation alloc] init] autorelease];
    o2.name=@"o2";
    [queue addOperation:o2];
   
    [NSThread sleepForTimeInterval:1];
   
    MyOperation *o3=[[[MyOperation alloc] init] autorelease];
    o3.name=@"o3";
    [o3 setQueuePriority:NSOperationQueuePriorityHigh];
    [queue addOperation:o3];

运行效果:

2011-07-26 14:47:23.822 NSOperationQueueDemo[27495:6003] run operation: o1

2011-07-26 14:47:26.823 NSOperationQueueDemo[27495:6003] run operation: o3
2011-07-26 14:47:29.824 NSOperationQueueDemo[27495:6203] run operation: o2

可见,操作3成功的插到第一个等待操作(操作2)之前执行了。

[ios2]使用NSOperationQueue简化多线程开发和队列的优先级 【转】的更多相关文章

  1. 使用NSOperationQueue简化多线程开发

    多线程开发是一件需要特别精心的事情,即使是对有多年开发经验的工程师来说. 为了能让初级开发工程师也能使用多线程,同时还要简化复杂性.各种编程工具提供了各自的办法.对于iOS来说,建议在尽可能的情况下避 ...

  2. iOS多线程开发

    概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操 ...

  3. 玩转iOS开发 - 多线程开发

    前言 本文主要介绍iOS多线程开发中使用的主要技术:NSOperation, GCD. NSThread, pthread. 内容依照开发中的优先推荐使用的顺序进行介绍,涉及多线程底层知识比較多的NS ...

  4. iOS多线程开发--NSThread NSOperation GCD

    多线程 当用户播放音频.下载资源.进行图像处理时往往希望做这些事情的时候其他操作不会被中 断或者希望这些操作过程中更加顺畅.在单线程中一个线程只能做一件事情,一件事情处理不完另一件事就不能开始,这样势 ...

  5. C#为什么要多线程开发(一)

    首先说下多线程出现的原因: 为了解决负载均衡问题,充分利用CPU资源.为了提高CPU的使用率,采用多线程的方式去同时完成几件事情而不互相干扰.为了处理大量的IO操作时或处理的情况需要花费大量的时间等等 ...

  6. 多线程开发之二 NSOperation

    效果如下: ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UITableViewControll ...

  7. iOS多线程开发资源抢夺和线程间的通讯问题

    说到多线程就不得不提多线程中的锁机制,多线程操作过程中往往多个线程是并发执行的,同一个资源可能被多个线程同时访问,造成资源抢夺,这个过程中如果没有锁机制往往会造成重大问题.举例来说,每年春节都是一票难 ...

  8. IOS多线程知识总结/队列概念/GCD/主队列/并行队列/全局队列/主队列/串行队列/同步任务/异步任务区别(附代码)

    进程:正在进行中的程序被称为进程,负责程序运行的内存分配;每一个进程都有自己独立的虚拟内存空间 线程:线程是进程中一个独立的执行路径(控制单元);一个进程中至少包含一条线程,即主线程 队列 dispa ...

  9. IOS多线程知识总结/队列概念/GCD/串行/并行/同步/异步

    进程:正在进行中的程序被称为进程,负责程序运行的内存分配;每一个进程都有自己独立的虚拟内存空间: 线程:线程是进程中一个独立的执行路径(控制单元);一个进程中至少包含一条线程,即主线程. 队列:dis ...

随机推荐

  1. elasticsearch集群搭建实例

    elasticsearch集群搭建实例 下个月又开始搞搜索了,几个月没动这块还好没有落下. 晚上在自己虚拟机上搭建了一个简易搜索集群,分享一下. 操作系统环境: Red Hat 4.8.2-16 el ...

  2. Java 多并发之原子访问(Atomic Access)

    在编程中,一个原子操作是只会出现一次的.一个原子操作在中间不会停止:要么全部发生要么一点也不发生.我们只有在原子操作完成之后才会看到原子操作的具体影响. 甚至是非常简单的表达式能够构造分解为简单操作的 ...

  3. CI框架 .htaccess 隐藏url在index.php解决方案

    CodeIgniter(下面简称"CI")是一款国外优秀的PHP轻量级MVC框架,它支持PHP4和PHP5.是开发中小型可拓展性需求高的Web应用程序的利器.眼下你所见到的这个博客 ...

  4. MySQL之 ALTER vs CHANGE vs MODIFY COLUMN

    1.ALTER COLUMN 用于设置或者移除某一列的默认(缺省)值, 1.1用法 ALTER TABLE MyTable ALTER COLUMN foo SET DEFAULT 'bar'; AL ...

  5. Visual Studio 2015 & C#6.0

      Visual Studio 2015 & C#6.0 试用报告,持续更新.   昨天早上看到了.net开源的消息,我是非常兴奋的,毕竟局限于Windows的.NET经常被人唾弃.VB暂且不 ...

  6. leetcode N-QueensII

    题目和上一题一样,就是要求输出有多少种结果.最直接的就是,只要在上一题的代码return ans.size();就可以了.果然也是AC了. 然后我翻看了几种别人写的,暂时还没有找到复杂度可以比上一题降 ...

  7. IntelliJ IDEA 发布13版本——创造java奇迹

    IntelliJ IDEA被公认为业界最好的Java开发平台.此次发布的了13版本,更是集合了与Java EE.Android.Spring.Scala和Gradle最新合作与支持. Java EE  ...

  8. 使用Windows2003创建DNS服务器 - 进阶者系列 - 学习者系列文章

    Windows 2003的DNS服务器的配置还是比较简单的.下面简要介绍下DNS服务器的配置. 1.    打开控制面板,选择 添加删除Windows组件,选择 网络服务 ,选择 详细信息,选择 域名 ...

  9. 淘宝code

    淘宝code 相信大家都听说过GitHub,也有很多人在用,但是GitHub毕竟在国外,速度不是很给力,而且安装过程也是很漫长.今天来给大家介绍一个国内的免费的开源项目平台,当然也是一个SVN版本控制 ...

  10. mysql的事物

    所谓的事物就是一组原子性的SQL语句,或者说是一个独立的工作单元. 1.事物拥有四大特征: ①原子性(atomicity):一个事物必须被分为一个不可分割的的最小单元,整个事物中的所有操作要么全部提交 ...