有人怎么盗取qq号我的qq号

[iOS] IOS 缓存管理之 YYCache 使用 - 推酷
[iOS] IOS 缓存管理之 YYCache 使用
最近一直在致力于为公司app添加缓存功能,为了寻找一个最佳方案,这几天先做个技术预研,经过这两天的查找资料基本上确定了两个开源框架进行选择,这两个开源框架分别是:PINCache、YYCache,上篇已经简单介绍了PINCache使用,本篇主要来学习一下YYCache的使用方式,以及和PINCache性能的简单对比。
关于YYCache
1. 内存缓存(YYMemoryCache)
存储的单元是_YYLinkedMapNode,除了key和value外,还存储了它的前后Node的地址_prev,_next.整个实现基于_YYLinkedMap,它是一个双向链表,除了存储了字典_dic外,还存储了头结点和尾节点.它实现的功能很简单,就是:有新数据了插入链表头部,访问过的数据结点移到头部,内存紧张时把尾部的结点移除.就这样实现了淘汰算法.因为内存访问速度很快,锁占用的时间少,所以用的速度最快的OSSpinLockLock
2. 硬盘缓存(YYDiskCache)
采用的是文件和数据库相互配合的方式.有一个参数inlineThreshold,默认20KB,小于它存数据库,大于它存文件.能获得效率的提高.key:path,value:cache存储在NSMapTable里.根据path获得cache,进行一系列的set,get,remove操作更底层的是YYKVStorage,它能直接对sqlite和文件系统进行读写.每次内存超过限制时,select key, filename, size from manifest order by last_access_time desc limit ?1会根据时间排序来删除最近不常用的数据.硬盘访问的时间比较长,如果用OSSpinLockLock锁会造成CPU消耗过大,所以用的dispatch_semaphore_wait来做.
YYCache使用
1.同步方式
//模拟数据
NSString *value=@&I want to know who is lcj ?&;
//模拟一个key
//同步方式
NSString *key=@&key&;
YYCache *yyCache=[YYCache cacheWithName:@&LCJCache&];
//根据key写入缓存value
[yyCache setObject:value forKey:key];
//判断缓存是否存在
BOOL isContains=[yyCache containsObjectForKey:key];
NSLog(@&containsObject : %@&, isContains?@&YES&:@&NO&);
//根据key读取数据
id vuale=[yyCache objectForKey:key];
NSLog(@&value : %@&,vuale);
//根据key移除缓存
[yyCache removeObjectForKey:key];
//移除所有缓存
[yyCache removeAllObjects];
2.异步方式
//模拟数据
NSString *value=@&I want to know who is lcj ?&;
//模拟一个key
//异步方式
NSString *key=@&key&;
YYCache *yyCache=[YYCache cacheWithName:@&LCJCache&];
//根据key写入缓存value
[yyCache setObject:value forKey:key withBlock:^{
NSLog(@&setObject sucess&);
//判断缓存是否存在
[yyCache containsObjectForKey:key withBlock:^(NSString * _Nonnull key, BOOL contains) {
NSLog(@&containsObject : %@&, contains?@&YES&:@&NO&);
//根据key读取数据
[yyCache objectForKey:key withBlock:^(NSString * _Nonnull key, id&NSCoding&
_Nonnull object) {
NSLog(@&objectForKey : %@&,object);
//根据key移除缓存
[yyCache removeObjectForKey:key withBlock:^(NSString * _Nonnull key) {
NSLog(@&removeObjectForKey %@&,key);
//移除所有缓存
[yyCache removeAllObjectsWithBlock:^{
NSLog(@&removeAllObjects sucess&);
//移除所有缓存带进度
[yyCache removeAllObjectsWithProgressBlock:^(int removedCount, int totalCount) {
NSLog(@&removeAllObjects removedCount :%d
totalCount : %d&,removedCount,totalCount);
} endBlock:^(BOOL error) {
if(!error){
NSLog(@&removeAllObjects sucess&);
NSLog(@&removeAllObjects error&);
YYCache缓存LRU清理
LRU(Least Recently Used)算法大家都比较熟悉,翻译过来就是“最近最少使用”,LRU缓存就是使用这种原理实现,简单的说就是缓存一定量的数据,当超过设定的阈值时就把一些过期的数据删除掉,比如我们缓存10000条数据,当数据小于10000时可以随意添加,当超过10000时就需要把新的数据添加进来,同时要把过期数据删除,以确保我们最大缓存10000条,那怎么确定删除哪条过期数据呢,采用LRU算法实现的话就是将最老的数据删掉。接下来我们测试一下
YYCache *yyCache=[YYCache cacheWithName:@&LCJCache&];
[yyCache.memoryCache setCountLimit:50];//内存最大缓存数据个数
[yyCache.memoryCache setCostLimit:1*1024];//内存最大缓存开销 目前这个毫无用处
[yyCache.diskCache setCostLimit:10*1024];//磁盘最大缓存开销
[yyCache.diskCache setCountLimit:50];//磁盘最大缓存数据个数
[yyCache.diskCache setAutoTrimInterval:60];//设置磁盘lru动态清理频率 默认 60秒
模拟一下清理
for(int i=0 ;i&100;i++){
//模拟数据
NSString *value=@&I want to know who is lcj ?&;
//模拟一个key
NSString *key=[NSString stringWithFormat:@&key%d&,i];
[yyCache setObject:value forKey:key];
NSLog(@&yyCache.memoryCache.totalCost:%lu&,(unsigned long)yyCache.memoryCache.totalCost);
NSLog(@&yyCache.memoryCache.costLimit:%lu&,(unsigned long)yyCache.memoryCache.costLimit);
NSLog(@&yyCache.memoryCache.totalCount:%lu&,(unsigned long)yyCache.memoryCache.totalCount);
NSLog(@&yyCache.memoryCache.countLimit:%lu&,(unsigned long)yyCache.memoryCache.countLimit);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(120 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@&yyCache.diskCache.totalCost:%lu&,(unsigned long)yyCache.diskCache.totalCost);
NSLog(@&yyCache.diskCache.costLimit:%lu&,(unsigned long)yyCache.diskCache.costLimit);
NSLog(@&yyCache.diskCache.totalCount:%lu&,(unsigned long)yyCache.diskCache.totalCount);
NSLog(@&yyCache.diskCache.countLimit:%lu&,(unsigned long)yyCache.diskCache.countLimit);
for(int i=0 ;i&100;i++){
//模拟一个key
NSString *key=[NSString stringWithFormat:@&whoislcj%d&,i];
id vuale=[yyCache objectForKey:key];
NSLog(@&key :%@ value : %@&,key ,vuale);
YYCache和PINCache一样并没有实现基于最大内存开销进行LRU,不过YYCache实现了最大缓存数据个数进行LRU清理,这一点也是选择YYCache原因之一,对于YYCache磁盘LRU清理并不是及时清理,而是后台开启一个定时任务进行RLU清理操作,定时时间默认是60s。
YYCache与PINCache对比
对于我这里的使用场景大部分用于缓存json字符串,我这里就以存储字符串来对比一下写入与读取效率
1.写入性能对比
//模拟数据
NSString *value=@&I want to know who is lcj ?&;
//模拟一个key
NSString *key=@&key&;
YYCache *yyCache=[YYCache cacheWithName:@&LCJCache&];
//写入数据
CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
[yyCache setObject:value forKey:key withBlock:^{
CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
NSLog(@& yyCache async setObject time cost: %0.5f&, end - start);
CFAbsoluteTime start1 = CFAbsoluteTimeGetCurrent();
[yyCache setObject:value forKey:key];
CFAbsoluteTime end1 = CFAbsoluteTimeGetCurrent();
NSLog(@& yyCache sync setObject time cost: %0.5f&, end1 - start1);
//PINCache
//模拟数据
NSString *value=@&I want to know who is lcj ?&;
//模拟一个key
NSString *key=@&key&;
PINCache *pinCache=[PINCache sharedCache];
//写入数据
CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
[pinCache setObject:value forKey:key block:^(PINCache * _Nonnull cache, NSString * _Nonnull key, id
_Nullable object) {
CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
NSLog(@& pincache async setObject time cost: %0.5f&, end - start);
CFAbsoluteTime start1 = CFAbsoluteTimeGetCurrent();
[pinCache setObject:value forKey:key];
CFAbsoluteTime end1 = CFAbsoluteTimeGetCurrent();
NSLog(@& pinCache sync setObject time cost: %0.5f&, end1 - start1);
通过上面的测试可以看出 同样大小的数据,无论同步方式还是异步方式,YYCache性能都要由于PINCache。
2.读取性能对比
YYCache *yyCache=[YYCache cacheWithName:@&LCJCache&];
//模拟一个key
NSString *key=@&key&;
CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
//读取数据
[yyCache objectForKey:key withBlock:^(NSString * _Nonnull key, id&NSCoding&
_Nonnull object) {
CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
NSLog(@& yyCache async objectForKey time cost: %0.5f&, end - start);
CFAbsoluteTime start1 = CFAbsoluteTimeGetCurrent();
[yyCache objectForKey:key];
CFAbsoluteTime
end1 = CFAbsoluteTimeGetCurrent();
NSLog(@& yyCache sync objectForKey time cost: %0.5f&, end1 - start1);
运行结果:
PINCache *pinCache=[PINCache sharedCache];
//模拟一个key
NSString *key=@&key&;
CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
//读取数据
[pinCache objectForKey:key block:^(PINCache * _Nonnull cache, NSString * _Nonnull key, id
_Nullable object) {
CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
NSLog(@& pincache async objectForKey time cost: %0.5f&, end - start);
CFAbsoluteTime start1 = CFAbsoluteTimeGetCurrent();
[pinCache objectForKey:key];
CFAbsoluteTime end1 = CFAbsoluteTimeGetCurrent();
NSLog(@& pinCache objectForKey time cost: %0.5f&, end1 - start1);
运行结果:
通过运行结果,在读取方面YYCache也是优于PINCache。
经过一番查阅资料和自己写例子测试,最终项目中决定使用YYCache进行缓存管理。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致HTTP/TCP(10)
HTTP请求中的缓存(cache)流程
当资源第一次被访问的时候,HTTP头部如下
(Request-Line)& GET /a.html HTTP/1.1
Host& & 127.0.0.1
User-Agent& Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.0.15) Gecko/ Ubuntu/9.04 (jaunty) Firefox/3.0.15
Accept& & & & & & & text/html,application/xhtml+xml,application/q=0.9,*/*;q=0.8
Accept-Language& & &zh-cn,q=0.5
Accept-Encoding& & &gzip,deflate
Accept-Charset& & & gb2312,utf-8;q=0.7,;q=0.7
Keep-Alive& & & & & 300
Connection& & & & & keep-alive
HTTP返回头部如下
(Status-Line)& & & &HTTP/1.1 200 OK
Date& & & & & & & & Thu, 26 Nov :54 GMT
Server& & & & & & & Apache/2.2.11 (Unix) PHP/5.2.9
Last-Modified& & & &Thu, 26 Nov :19 GMT
Etag& & & & & & & & “8fb8b-14-4794674acdcc0″
Accept-Ranges& & & &bytes
Content-Length& & & 20
Keep-Alive& & & & & timeout=5, max=100
Connection& & & & & Keep-Alive
Content-Type& & & & text/html
当资源第一次被访问的时候,http返回200的状态码,并在头部携带上当前资源的一些描述信息,如
Last-Modified& & & // 指示最后修改的时间
Etag& & & & & & & & // 指示资源的状态唯一标识
Expires& & & & & & &// 指示资源在浏览器缓存中的过期时间
接着浏览器会将文件缓存到Cache目录下,并同时保存文件的上述信息
当第二次请求该文件时,浏览器会先检查Cache目录下是否含有该文件,如果有,并且还没到Expires设置的时间,即文件还没有过期,那么此时浏览器将直接从Cache目录中读取文件,而不再发送请求
如果文件此时已经过期,则浏览器会发送一次HTTP请求到WebServer,并在头部携带上当前文件的如下信息
If-Modified-Since& &Thu, 26 Nov :19 GMT
If-None-Match& & & &”8fb8b-14-4794674acdcc0″
即把上一次修改的时间,以及上一次请求返回的Etag值一起发送给服务器。服务器在接收到这个请求的时候,先解析Header里头的信息,然后校验该头部信息。 如果该文件从上次时间到现在都没有过修改或者Etag信息没有变化,则服务端将直接返回一个304的状态,而不再返回文件资源,状态头部如下
(Status-Line)& & & &HTTP/1.1 304 Not Modified
Date& & & & & & & & Thu, 26 Nov :07 GMT
Server& & & & & & & Apache/2.2.11 (Unix) PHP/5.2.9
Connection& & & & & Keep-Alive
Keep-Alive& & & & & timeout=5, max=100
Etag& & & & & & & & “8fb8b-14-4794674acdcc0″
这样,就能够很大程度上减少网络带宽以及提升用户的浏览器体验。 当然,如果服务器经过匹配发现文件修改过了,就会将文件资源返回,并带上新文件状态信息。
Pragma头域用来包含实现特定的指令,最常用的是Pragma:no-cache。在HTTP/1.1协议中,它的含义和Cache- Control:no-cache相同。
文件在本地缓存的过期时间,如果浏览器发现缓存中的文件没有过期,则不发送请求(有例外,后面介绍)
Cache-Control
Cache -Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置 Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括no-cache、no-store、max-age、 max-stale、min-fresh、only-if-cached,响应消息中的指令包括public、private、no-cache、no- store、no-transform、must-revalidate、proxy-revalidate、max-age。各个消息中的指令含义如
下:   Public指示响应可被任何缓存区缓存。   Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请 求无效。   no-cache指示请求或响应消息不能缓存   no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。   max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。   min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
  max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应 消息。
Etag/If-None-Match
一对验证文件实体的标记 “Entity Tag”的响应/请求头 Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的
Last-Modified/If-Modified-Since
一对验证文件的修改时间的响应/请求头
Expires、Cache-Control、Last-Modified、ETag是RFC 2616(HTTP/1.1)协议中和网页缓存相关的几个字段。 前两个用来控制缓存的失效日期,浏览器可通过它来判定,需不需要发出HTTP请求; 后两个用来验证网页的有效性,服务器端利用它来验证这个文件是否需要重新返回
Last-Modified VS Etag
既然有了Last-Modified,为什么还要用ETag字段呢?因为如果在一秒钟之内对一个文件进行两次更改,Last-Modified就会不正确。因此,HTTP/1.1利用Entity Tag头提供了更加严格的验证。
不同的情况
上面描述的是一个普通的浏览器缓存状态,在实际应用中,如页面跳转(点击页面链接跳转,window.open,在地址栏敲回车,刷新页面)等操作,会有一些区别
普通页面跳转
普通页面跳转包括链接点击跳转,用js脚本打开新页面(window.open) 无缓存情况下,请求会返回所有资源结果 设置Expires并且未过期时,浏览器将不会发出http请求 如果Expires过期,则会发送相应请求,并附带上Last-Modifed等信息,供服务器校验
页面刷新(F5)
这种情况一下,一般会看到很多304的请求,就是说即便资源设置了Expires且未过期,浏览器也会发送相应请求 IE和FF稍有区别 IE:
If-Modified-Since& &Wed, 18 Nov :52 GMT
If-None-Match& &”″
Pragma: no-cache& & // 禁止缓存
If-Modified-Since& &Wed, 18 Nov :52 GMT
If-None-Match& &”″
Cache-Control& &max-age=0& &// 文件立即过期
强制刷新(Ctrl+F5)
效果和无缓存时候一致,返回200的结果
该文章出处:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:8453次
排名:千里之外
原创:64篇
转载:11篇
(32)(2)(1)(3)(9)(26)(1)YYCache 源码分析(二) - 滚动_【北京联盟】
YYCache 源码分析(二)
/ 作者:小易
北京联盟摘要:
YYCache 源码分析(二),上一篇:
下一篇: 。(点击上方公众号,可快速关注) 来源:汉斯哈哈哈 链接:/p/492c3c3a0485 本文分析YYMemoryCache实现原理: YYMemoryCache是内存缓存,所以存取速度非常快,主要用到两种数据结构的LRU淘汰算法 1.LRU Cache的容量是有限的,当Cache的
(点击上方公众号,可快速关注)来源:汉斯哈哈哈链接:/p/492c3c3a0485本文分析YYMemoryCache实现原理:YYMemoryCache是内存缓存,所以存取速度非常快,主要用到两种数据结构的LRU淘汰算法1.LRUCache的容量是有限的,当Cache的空间都被占满后,如果再次发生缓存失效,就必须选择一个缓存块来替换掉.LRU法是依据各块使用的情况, 总是选择那个最长时间未被使用的块替换。这种方法比较好地反映了程序局部性规律2.LRU主要采用两种数据结构实现双向链表(Doubly Linked List)哈希表(Dictionary)3.对一个Cache的操作无非三种:插入、替换、查找插入:当Cache未满时,新的数据项只需插到双链表头部即可替换:当Cache已满时,将新的数据项插到双链表头部,并删除双链表的尾结点即可查找:每次数据项被查询到时,都将此数据项到链表头部4.分析图(分析源码时可以对照该图)5.YYMemoryCache.m里的两个分类链表节点_YYLinkedMapNode:@interface _YYLinkedMapNode : NSObject {@package// 指向前一个节点__unsafe_unretained _YYLinkedMapNode *_ // retained by dic// 指向后一个节点__unsafe_unretained _YYLinkedMapNode *_ // retained by dic// 缓存keyid _// 缓存对象id _// 当前缓存内存开销NSUInteger _// 缓存时间NSTimeInterval _}@end链表_YYLinkedMap:@interface _YYLinkedMap : NSObject {@package// 用字典保存所有节点_YYLinkedMapNode (为什么不用oc字典?因为用CFMutableDictionaryRef效率高,毕竟基于c)CFMutableDictionaryRef _// 总缓存开销NSUInteger _totalC// 总缓存数量NSUInteger _totalC// 链表头节点_YYLinkedMapNode *_// 链表尾节点_YYLinkedMapNode *_// 是否在主线程上,异步释放 _YYLinkedMapNode对象BOOL _releaseOnMainT// 是否异步释放 _YYLinkedMapNode对象BOOL _releaseA}// 添加节点到链表头节点- (void)insertNodeAtHead:(_YYLinkedMapNode *)// 移动当前节点到链表头节点- (void)bringNodeToHead:(_YYLinkedMapNode *)// 移除链表节点- (void)removeNode:(_YYLinkedMapNode *)// 移除链表尾节点(如果存在)- (_YYLinkedMapNode *)removeTailN// 移除所有缓存- (void)removeA@end方法插入、替换、查找方法实现:// 添加节点到链表头节点- (void)insertNodeAtHead:(_YYLinkedMapNode *)node {// 字典保存链表节点nodeCFDictionarySetValue(_dic, (__bridge const void *)(node-&_key), (__bridge const void *)(node));// 叠加该缓存开销到总内存开销_totalCost += node-&_// 总缓存数+1_totalCount++;if (_head) {// 存在链表头,取代当前表头node-&_next = __head-&_prev =// 重新赋值链表表头临时变量_head_head =} else {// 不存在链表头_head = _tail =}}存在表头情况图形分析(其他情况不用图分析,自己想象吧,呵呵)// 移动当前节点到链表头节点- (void)bringNodeToHead:(_YYLinkedMapNode *)node {// 当前节点已是链表头节点if (_head == node)if (_tail == node) {//**如果node是链表尾节点**// 把node指向的上一个节点赋值给链表尾节点_tail = node-&_// 把链表尾节点指向的下一个节点赋值nil_tail-&_next =} else {//**如果node是非链表尾节点和链表头节点**// 把node指向的上一个节点赋值給node指向的下一个节点node指向的上一个节点node-&_next-&_prev = node-&_// 把node指向的下一个节点赋值给node指向的上一个节点node指向的下一个节点node-&_prev-&_next = node-&_}// 把链表头节点赋值给node指向的下一个节点node-&_next = _// 把node指向的上一个节点赋值nilnode-&_prev =// 把节点赋值给链表头节点的指向的上一个节点_head-&_prev =_head =}// 移除节点- (void)removeNode:(_YYLinkedMapNode *)node {// 从字典中移除nodeCFDictionaryRemoveValue(_dic, (__bridge const void *)(node-&_key));// 减掉总内存消耗_totalCost -= node-&_// // 总缓存数-1_totalCount--;// 重新连接链表(看图分析吧)if (node-&_next) node-&_next-&_prev = node-&_if (node-&_prev) node-&_prev-&_next = node-&_if (_head == node) _head = node-&_if (_tail == node) _tail = node-&_}// 移除尾节点(如果存在)- (_YYLinkedMapNode *)removeTailNode {if (!_tail)// 拷贝一份要删除的尾节点指针_YYLinkedMapNode *tail = _// 移除链表尾节点CFDictionaryRemoveValue(_dic, (__bridge const void *)(_tail-&_key));// 减掉总内存消耗_totalCost -= _tail-&_// 总缓存数-1_totalCount--;if (_head == _tail) {// 清除节点,链表上已无节点了_head = _tail =} else {// 设倒数第二个节点为链表尾节点_tail = _tail-&__tail-&_next =}// 返回完tail后_tail将会释放}// 移除所有缓存- (void)removeAll {// 清空内存开销与缓存数量_totalCost = 0;_totalCount = 0;// 清空头尾节点_head =_tail =if (CFDictionaryGetCount(_dic) & 0) {// 拷贝一份字典CFMutableDictionaryRef holder = _// 重新分配新的空间_dic = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);if (_releaseAsynchronously) {// 异步释放缓存dispatch_queue_t queue = _releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue();dispatch_async(queue, ^{CFRelease(holder); // hold and release in specified queue});} else if (_releaseOnMainThread && !pthread_main_np()) {// 主线程上释放缓存dispatch_async(dispatch_get_main_queue(), ^{CFRelease(holder); // hold and release in specified queue});} else {// 同步释放缓存CFRelease(holder);}}}YYMemoryCache.m实现分析(如果上面弄清楚,接下来就简单多了),增删改都是调用上面的方法,下面分析查找与添加缓存方法实现// 查找缓存- (id)objectForKey:(id)key {if (!key)// 加锁,防止资源竞争// OSSpinLock 自旋锁,性能最高的锁。原理很简单,就是一直 do while 忙等。它的缺点是当等待时会消耗大量 CPU 资源,所以它不适用于较长时间的任务。对于内存缓存的存取来说,它非常合适。pthread_mutex_lock(&_lock);// _lru为链表_YYLinkedMap,全部节点存在_lru-&_dic中// 获取节点_YYLinkedMapNode *node = CFDictionaryGetValue(_lru-&_dic, (__bridge const void *)(key));if (node) {//** 有对应缓存 **// 重新更新缓存时间node-&_time = CACurrentMediaTime();// 把当前node移到链表表头(为什么移到表头?根据LRU淘汰算法:Cache的容量是有限的,当Cache的空间都被占满后,如果再次发生缓存失效,就必须选择一个缓存块来替换掉.LRU法是依据各块使用的情况, 总是选择那个最长时间未被使用的块替换。这种方法比较好地反映了程序局部性规律)[_lru bringNodeToHead:node];}// 解锁pthread_mutex_unlock(&_lock);// 有缓存则返回缓存值return node ? node-&_value :}// 添加缓存- (void)setObject:(id)object forKey:(id)key withCost:(NSUInteger)cost {if (!key)if (!object) {// ** 缓存对象为空,移除缓存 **[self removeObjectForKey:key];}// 加锁pthread_mutex_lock(&_lock);// 查找缓存_YYLinkedMapNode *node = CFDictionaryGetValue(_lru-&_dic, (__bridge const void *)(key));// 当前时间NSTimeInterval now = CACurrentMediaTime();if (node) {//** 之前有缓存,更新旧缓存 **// 更新值_lru-&_totalCost -= node-&__lru-&_totalCost +=node-&_cost =node-&_time =node-&_value = /p/// 移动节点到链表表头[_lru bringNodeToHead:node];} else {//** 之前未有缓存,添加新缓存 **// 新建节点node = [_YYLinkedMapNode new];node-&_cost =node-&_time =node-&_key =node-&_value = /p/// 添加节点到表头[_lru insertNodeAtHead:node];}if (_lru-&_totalCost & _costLimit) {// ** 总缓存开销大于设定的开销 **// 异步清理最久未使用的缓存dispatch_async(_queue, ^{[self trimToCost:_costLimit];});}if (_lru-&_totalCount & _countLimit) {// ** 总缓存数量大于设定的数量 **// 移除链表尾节点(最久未访问的缓存)_YYLinkedMapNode *node = [_lru removeTailNode];if (_lru-&_releaseAsynchronously) {dispatch_queue_t queue = _lru-&_releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue();dispatch_async(queue, ^{[node class]; //and release in queue});} else if (_lru-&_releaseOnMainThread && !pthread_main_np()) {dispatch_async(dispatch_get_main_queue(), ^{[node class]; //hold and release in queue});}}pthread_mutex_unlock(&_lock);}接下来会分析YYDiskCache实现原理【今日微信公号↓】更多推荐请看《值得关注的技术和设计公众号》其中推荐了包括技术、设计、极客和IT相亲相关的热门公众号。技术涵盖:Python、Web前端、Java、安卓、iOS、PHP、C/C++、.NET、Linux、数据库、运维、大数据、算法、IT职场等。点击《值得关注的技术和设计公众号》,发现精彩!iOS大全(iOShub)
YYCache 源码分析(二)
免责声明:本站文章除注明来源“北京联盟”外的文章均来自网络和网友投稿,著作权归原作者所有。北京联盟不承担任何连带责任!

我要回帖

更多关于 怎么盗取qq号 的文章

 

随机推荐