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

为了能让初级开发工程师也能使用多线程,同时还要简化复杂性。各种编程工具提供了各自的办法。对于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简化多线程开发的更多相关文章

  1. [ios2]使用NSOperationQueue简化多线程开发和队列的优先级 【转】

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

  2. iOS多线程开发

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

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

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

  4. 多线程开发之二 NSOperation

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

  5. Java之多线程开发时多条件Condition接口的使用

    转:http://blog.csdn.net/a352193394/article/details/39454157 我们在多线程开发中,可能会出现这种情况.就是一个线程需要另外一个线程满足某某条件才 ...

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

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

  7. 推荐 greenrobot eventbus,简化安卓开发,提高安卓维护性,优化安卓性能

    最近在研究移动开发,广泛的阅读有关cordova,apicloud,android资料.发现安卓的开发还是很简单的.再发现greenrobot eventbus开源框架不仅可以简化安卓开发,有可以大幅 ...

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

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

  9. ios多线程开发总结

    1>无论使用哪种方法进行多线程开发,每个线程启动后并不一定立即执行相应的操作,具体什么时候由系统调度(CPU空闲时就会执行). 2>更新UI应该在主线程(UI线程)中进行,并且推荐使用同步 ...

随机推荐

  1. TortoiseSVN文件夹及文件图标不显示解决方法---20150515

    由于自己的电脑是win7(64位)的,系统安装TortoiseSVN之后,其他的功能都能正常的使用,但是就是文件夹或文件夹的左下角就是不显示图标,这个问题前一段时间就遇到了(那个时候没找到合适的答案) ...

  2. (46)zabbix报警媒介:Jabber

    Jabber有第三方插件,能让Jabber用户和MSN.YahooMessager.ICQ等IM用户相互通讯.因为Google遵从Jabber协议,并且Google已经将Gtalk的服务器开放给了其它 ...

  3. 浅谈Session与Cookie的关系

    一.概念理解: 首先cookie是服务端识别客户的唯一标识的依据,客户在访问网站时候,服务端为了记住这个客户,会在服务端按照它的规则制作一个cookie数据,会将这个cookie数据保留在服务端一段时 ...

  4. Python9-day2 作业

    下列结果是什么? 6 or 2 >1     6 3 or 2 > 1  3 0 or 5<4  false 5 < 4 or 3  3 2 >1 or 6 True 3 ...

  5. Python网络爬虫(Get、Post抓取方式)

    简单的抓取网页 import urllib.request url="http://google.cn/" response=urllib.request.urlopen(url) ...

  6. Hi3519V101 Uboot和Kernel编译

    前面已经搭建好了Ubuntu下的海思开发环境,现在对编译Uboot和Kernel的过程做一个简单的记录.参考文档<Hi3519V101 U-boot 移植应用开发指南.pdf>和<H ...

  7. bs4--官方文档

    如何使用 将一段文档传入BeautifulSoup 的构造方法,就能得到一个文档的对象, 可以传入一段字符串或一个文件句柄. from bs4 import BeautifulSoup soup = ...

  8. luogu2526 [SHOI2001]小狗散步

    注意一个景点只能去一次. #include <iostream> #include <cstring> #include <cstdio> #include < ...

  9. matlab调用自己写的函数时报错: reference to a cleared variable

    原因是在自己写的函数中加了clear. 解决办法:自己定义的函数中不能加clear,可以加clc;

  10. POJ-1696 Space Ant 凸包版花式水过!

                                                         Space Ant 明天早上最后一科毛概了,竟然毫无复习之意,沉迷刷题无法自拔~~ 题意:说实 ...