NSOperationQueue高级运用:管理和调度里面线程池
来源:互联网 发布:摇钱树是什么软件 编辑:程序博客网 时间:2024/05/16 18:22
当你使用NSOperationQueue的时候,怎么按照你自己的意愿去管理每一个你add进去的NSOperation(进程的优先级,相同线程请求操作的新旧替换)
阅读本文需要理解KVO && KVC(个人认为,如果想成为一个越来越好的IOS developer,这个是必须要懂得的,还有core data)
一.demo(多线程下载图片):控制NSOperation执行的优先级,并且限制最大线程执行数目,若已经达到最大线程执行数目,又有新的线程进入队列,那么停止最老的一个线程,把他的位置让给最新进入的线程:
(为什么有最大线程个数的限制:主要考虑的是在移动网络的情况下,网络上行和下行带宽的限制,给用户一个较好的体验,而不是闲线程过多时消耗过大,毕竟IOS不是MTK~)
1.自定义一个自己的NSOperationQueue:主要为了在NSOperationQueue init的时候加入一行代码
-(id)init
{
if (self = [superinit]) {
[selfsetMaxConcurrentOperationCount:10];
[selfaddObserver:selfforKeyPath:@"operations"options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOldcontext:nil];
}
returnself;
}
2.上行代码让你监控了NSOperationQueue 中的 NSOperation NSArray的变化,当有变化的时候,你会收到消息
我下面的代码是写一个(后进先执行的 进程队列管理)
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"operations"])
{
NSArray *oldOperation = [change objectForKey:@"old"];//变化之前的NSOperation Array
NSArray *newOperation = [change objectForKey:@"new"];//新的的NSOperation Array
//!注意A:此时队列里的所有线程仍然在执行,所以你此时取出的线程新旧数组,仅仅是一个参考值(他们可能其中一个在此时已经执行完毕了)
//第一个NSOperation加入,无需处理
if (newOperation.count == 1) {
return;
}
//进入的线程个数没有超过你设定的最大线程个数,所以无需管理他的优先级,因为所有的线程都在运行
if (self.operationCount <= self.maxConcurrentOperationCount) {
NSLog(@"add one operation to queue.do not need to change operation priority level");
return;
}
//进入线程队列的线程个数过多,所以停止最老的一个线程,执行最新的线程
if (newOperation.count > oldOperation.count) {
//先停止整个线程执行队列:若不停止,你这段代码执行的同时,其余线程仍然在执行,此时你所取的一些状态值只是一个参考值,很有可能在你代码执行了2行后,有一个线程就执行完毕了!
[self setSuspended:YES];
NSOperation *operation;
//需要停止的线程个数
int needcancelNum = self.operationCount - self.maxConcurrentOperationCount;
int i = 0;
for (operation in newOperation) {
if ([operation isFinished]) {
//一个线程已经执行完毕:为什么:参照 注意A
needcancelNum--;
NSLog(@"%@ is finished", operation);
}else if(i < needcancelNum)
{
//取消最旧的线程执行
[operation cancel];
NSLog(@"%@ is canceld", operation);
i++;
}else
{
//将其余所有线程的优先级设置为0.8
operation.threadPriority = 0.8;
}
}
//此时operation 是最新的一个线程,将其优先级设置为1.0(最高)
operation.threadPriority = 1.0;
//恢复线程队列的运行
[self setSuspended:NO];
}
}
}
二:相同线程请求操作的新旧替换
如何识别一个线程的功能是相同的
(使用场景:由于用户的刷新操作,你需要下载最新网络数据对应的图片,此时若前一次网络需要下载的图片还没有下载完成,你需要用你最新的线程去替换旧的线程)
我想到的方案是,用一个自己定义过的NSOperation,在里面加入一个属性,线程名字。
这样在上文所述 线程队列的NSOperation数组发生了变化时,你可以查询所有线程的名字,然后检测下是否有相同名字的线程进入了线程队列,如果有的话,你需要取消旧的那个线程。
一样在
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 中加入以下代码: PicLoadAndCacheOperation 是一个custom NSOperation
//new operation comes more than 1,so check Did their have the same name
if((newOperation.count - oldOperation.count) > 1)
{
[self setSuspended:YES];
for (int i = 0; i < newOperation.count; i++)
{
PicLoadAndCacheOperation *keyOperation = [newOperation objectAtIndex:i];
for (int j = i + 1; j < newOperation.count; j++)
{
PicLoadAndCacheOperation *comparedOperation = [newOperation objectAtIndex:j];
if ([comparedOperation.operationName isEqualToString:keyOperation.operationName])
{
[keyOperation cancel];
continue;
}
}
}
[self setSuspended:NO];
}
//instead last thread by new thread by it's operation name
else if ((newOperation.count - oldOperation.count) == 1) {
[self setSuspended:YES];
PicLoadAndCacheOperation *Operation = [newOperation objectAtIndex:oldOperation.count];
NSString *newOperationName = Operation.operationName;
for (PicLoadAndCacheOperation *oOperation in oldOperation) {
NSString *oldOperationName = oOperation.operationName;
if ([oldOperationName isEqualToString:newOperationName]) {
[oOperation cancel];
[self setSuspended:NO];
return;
}
}
[self setSuspended:NO];
}
- NSOperationQueue高级运用:管理和调度里面线程池
- NSOperationQueue管理线程(转)
- 线程池NSoperationQueue和GCD比较
- 线程池NSOperationQueue
- 【高级线程管理】线程池
- NSOperationQueue、NSRunLoop和线程安全
- NSOperationQueue、NSRunLoop和线程安全
- NSOperationQueue、NSRunLoop和线程安全
- Windows的线程管理和调度机制
- Windows的线程管理和调度机制
- Windows线程管理和调度机制概述
- NSOperationQueue 线程池的使用
- Windows高级编程之线程调度、优先级和亲缘性
- NSOperationQueue、NSRunLoop和线程安全 学习笔记
- 深入学习:NSOperationQueue, NSRunLoop和线程安全
- 操作系统(二):进程和线程管理_3_处理机调度
- NSOperationQueue—高级功能
- rtems线程管理与调度
- Android OTA 升级之二:脚本 ota_from_target_files
- jsp网页视频播放器
- iOS ASI http 框架详解
- MySQL error: 145 (Table 'xxx' is marked as crashed and should be repaired
- Linux内核裁剪与编译(下篇)--基于2.6.30内核
- NSOperationQueue高级运用:管理和调度里面线程池
- 用ruby grape搭建微信公众平台回复后台
- Android OTA 升级之三:生成recovery.img
- VC项目配置基础
- ECSHOP商品页,加入购物车弹出浮动层,仿淘宝效果
- 常用排序
- ArcSDE 10.1安装、配置、连接 (SQL Server 2008)
- EAN码详解
- IOS之同步请求、异步请求、GET请求、POST请求