博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【转载】 iphone使用NSOperationQueue简化多线程开发
阅读量:6225 次
发布时间:2019-06-21

本文共 2976 字,大约阅读时间需要 9 分钟。

1:原文摘自:

 

使用NSOperationQueue简化多线程开发

来自  
Fgamers
   
860 次阅读 评论 (0)

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

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

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

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

编写最简单的示例

先写个最简单的示例。

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

头文件:

1234567
@interface MyTask : NSOperation {
int operationId; }  @property int operationId;  @end

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

m文件:

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

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

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

123456789
- (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秒钟后,日志打印完毕,类似这样:

12
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)增加多个操作,比如这样:

1234567891011121314
- (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];}

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

1234
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.

甚至有可能是这样:

1234
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.

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

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

处理操作之间的依赖关系

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

1234567891011121314151617
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];

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

控制线程池中的线程数

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

1
[queue setMaxConcurrentOperationCount:2];
 

转载地址:http://stuna.baihongyu.com/

你可能感兴趣的文章
C语言结构指针传递结构内容
查看>>
Python过渡性模块重载(递归重载模块)
查看>>
mysql错误信息的利用
查看>>
MyEclipse启动失败现象以及解决办法
查看>>
Vmware vSphere常见问题汇总(四)
查看>>
反编译Silverlight项目
查看>>
Serving websites from svn checkout considered harmful
查看>>
迁移SVN注意事项及操作方法
查看>>
linux 的GPT分区
查看>>
getRealPath()和getContextPath()的区别
查看>>
浅析:AD组添加成员后为何客户端要注销?
查看>>
System Center Data Protection Manager 2007补助说明
查看>>
Fortune 500市场占有率分析:Compute、CDN、DNS
查看>>
RHCE 学习笔记(33) - Postfix
查看>>
Windows Server群集感知更新(CAU)-上
查看>>
LVM磁盘管理技术案例讲解
查看>>
SCCM 2012系列13 操作系统播发②
查看>>
Memcached 分布式缓存系统部署与调试
查看>>
开源网络备份软件bacula(功能特点与原理)
查看>>
《Essential Linux Device Drivers》第2章(下)
查看>>