iOS只提供了非线程安全的数组。
如果要多线程并发的使用一个数组对象就必须要加锁,频繁加锁使代码的调用非常的麻烦。
我们需要多线程的读写锁在类的内部实现,所以需要对NSMutableArray进行封装,封装后的对象负责接受所有事件并将其转发给真正的NSMutableArray对象,并通过合理的调度使得其支持多线程并发。
新建一个对象来对NSMutableArray 数组进行封装,包含
dispatch_queue_t 调度队列对象 和一个
NSObject 具体操作对象作为成员变量
@implementation MultiThreadSafeObject
- (id)init
{
self = [super init];
if (self)
{
_mtsDispatchQueue = dispatch_queue_create("COM.MTS.MultiThreadSafeObject", NULL);
}
return self;
}
- (void)dealloc
{
_mtsDispatchQueue = nil;
_mtsContainer = nil;
}
我们再新建mtsMutableArray类继承自MultiThreadSafeObject并为其声明简单接口来支持其作为Array使用
#import "MultiThreadSafeObject.h"
@protocol mtsMutableArrayProtocol
@optional
- (id)lastObject;
- (id)objectAtIndex:(NSUInteger)index;
- (NSUInteger)count;
- (void)addObject:(id)anObject;
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
- (void)removeLastObject;
- (void)removeObjectAtIndex:(NSUInteger)index;
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
@end
@interface mtsMutableArray : MultiThreadSafeObject<mtsMutableArrayProtocol>
@end
#pragma mark - public method
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
return [[_mtsContainer class] instanceMethodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
NSMethodSignature *sig = [anInvocation valueForKey:@"_signature"];
const char *returnType = sig.methodReturnType;
//NSLog(@"%@ = > %@",anInvocation.target, NSStringFromSelector(anInvocation.selector));
//NSLog(@"%s",returnType);
if (!strcmp(returnType, "v"))
{
//没有返回值 setter方法 异步barrier
/** the setter method just use async dispatch
remove the barrier to make it faster when u r sure that invacations will not affect each other
*/
dispatch_barrier_async(_mtsDispatchQueue, ^{
[anInvocation invokeWithTarget:_mtsContainer];
});
}
else
{
//有返回值 getter方法 同步barrier
/** all getter method need sync dispatch
barrier make sure the result is correct
getter method need barrier in most ways unless u dont except this */
dispatch_barrier_sync(_mtsDispatchQueue, ^{
[anInvocation invokeWithTarget:_mtsContainer];
});
}
}
获取调度方法的返回值,如果是void型方法则使用异步调度,如果是getter类型的则使用同步调度,可以略微的提升性能。
可以通过继承等方法为不同类型的container指定不同的调度规则以确保在逻辑正常的情况下拥有最高的性能。
1. Controller/Service/DAO简介: Controller是管理业务(Service)调度和管理跳转的。 Service是管理具体的功能的。 Controller只负责管理,而Service负责实施。 DAO只完成增删改查,虽然可以1-n,n-n,1-1关联,模糊、动态、子查询都可以。但是无论多么复杂的查询,dao只是封装增删改查。至于增删查改如何去实现一..._filter层
1.项目的请求文件路径一般不能用于附件下载http://localhost:8101/dsmp-test/img/a1.jpg2.用于附件上传下载获取当前项目路径的方法(1)、request.getRealPath("/");//不推荐使用获取工程的根路径(2)、request.getRealPath(request.getRequestURI());//获取jsp的路径,这个方法..._idea获取项目路径
第六章 统计成绩小故事:话说逸凡逃掉了第6周星期三的课,班主任还是发觉了。期中考试后,班主任找来逸凡,没有批评,只是说帮他统计成绩。逸凡拿到一堆试卷,赶紧统计全班45人的平均分。一会儿,班主任又叫逸凡统计各个分数段的人数以及各分数段的比例。逸凡又将试卷重新翻开,一个一个地统计各个分数段的人数。 一、初次接触前面,我们使用变量来存储数据。由于逸凡要统计全班同学的平均分,所以_统计成绩的存储类型有哪些
C++有静态编译和动态编译,QT也是这样,就不多阐述了,懂得都懂。qt的静态编译很麻烦,主要是自己编译源码需要一大堆工具,还要看官方教程,这里把我编译的文件分享给大家,下载以后直接解压,添加qt版本就能用了,不会的话可以参考其他文章。这里有三个文件,前两个是我用VS2019编译的32位和64位版本,讲道理,Windows平台上,vs才是永远滴神,第三个是网上别人分享的,我没用过,前两个用的都没问题。链接:https://pan.baidu.com/s/1gtAi6KFozQ2gSv0DujSQxw_qt 怎么静态编译文件
mysql登陆基本操作:登陆:mysql -uroot -h127.0.0.1 -P3306 -pmysql -uroot -p(本机不用写host)退出mysql:ctrl+z+回车,或者exit端口号默认是3306,但是可以通过安装目录下的配置文件修改。使用流程引用API模块获取与数据库的连接执行sql语句与存储过程关闭数据库连接安装pymysqlpython3 与...
关于视频会议系统(WebRTC)的反思误区?究竟什么是信令,什么是事件思考一:怎样划分消息类别思考二:怎样理解信令服务器拆分后的结构是什么样子的?下面聊聊设计原则QQ交流群:697773082转载请注明出处:https://blog.csdn.net/impingo项目官网:https://pingos.io项目地址:https://github.com/im-pingo/pingos误区..._webrtc网络视频会议系统黑盒测试
这个文档描述了程序员要怎么样帮助HCS12X编译器来产生在数据访问上更加优化的代码。我们将讨论以下主题:地址转换(从逻辑地址到全局地址)使用逻辑地址定义一个变量并使用全局地址来访问它使用混合寻址模式来访问全局变量_codewarrior中取地址符
原文在这里“Win8微软输入法全拼和双拼的快捷切换”:https://jingyan.baidu.com/article/fb48e8be5a2a1e6e632e1447.html我的是Win10,测试了一下也是适用的。将下面的代码保存为bat文件运行即可@echo offset Mainkey=HKCU\SOFTWARE\Microsoft\InputMethod\Set_win10输入法双拼改变全拼
1 概述支持向量机(SVM,也称为支持向量网络),是机器学习中获得关注最多的算法。它源于统计学习理论,是除了集成学习算法之外,接触到的第一个强学习器。从算法的功能来看,SVM囊括了很多其他算法的功能:从分类效力来讲,SVM在无论线性还是非线性分类中,都是明星般的存在。在实际应用来看,SVM在各种实际问题中都表现非常优秀。它在手写识别数字和人脸识别中应用广泛,在文本和超文本的分类中举足轻重,因为SVM可以大量减少标准归纳(standard inductive)和转换设置(transductive s_sklearn svm
在从客户端向WCF服务端传送较大数据(>65535B)的时候,发现程序直接从Reference的BeginInvoke跳到EndInvoke,没有进入服务端的Service实际逻辑中,怀疑是由于数据过大超出限定导致的。报错信息:远程服务器返回了意外响应: (400) Bad Request。问题是我实际发送的数据是刚刚从WCF服务端接收过来的,...
最易懂的设计模式解析:单例模式(Singleton)前言今天我来全面总结一下Android开发中最常用的设计模式 - 单例模式。 关于设计模式的介绍,可以看下我之前写的:1分钟全面了解“设计模式”目录1. 引入1.1 解决的是什么问题之前说过,设...http://www.xiami.com/collect/207573283?spm=a1z1s.2929273.1561564893.2.v
硬盘分区及格式化Linux操作系统在安装过程中,必须对硬盘进行分区操作,并将分区格式化为不同的文件系统之后,才可以挂载使用。硬盘一般分为:IDE硬盘、SCSI硬盘和SATA硬盘在Linux中,IDE接口的设备被称为hdSCSI和SATA接口的设备被称为sd。第一块硬盘被称为sda,第二块称为adb……以此类推。硬盘的分区分为主分区和扩展分区。一个硬盘最多可以划分为4个主磁盘分区,分别..._实训步骤linux服务器新增两块硬盘,硬盘大小为20gb,在sdb盘上建3个分区,格式化