设计思路

利用YYCache来进行操作,实质操作分为了内存缓存操作(YYMemoryCache)和硬盘缓存操作(YYDiskCache)。内存缓存设计一般是在内存中开辟一个空间用以保存请求的数据(一般使用字典操作)。硬盘缓存设计即是将文件保存至本地,这种保存分为小文件保存和大文件保存,对于小文件保存使用数据库操作性能效率相对较高,对于大文件则使用直接存放。YYDiskCache为线程安全的类,其操作是基于YYKVStorage(线程不安全的类)的操作。以下为大致源码分析

主类YYCache

必须初始化名字 名字即为存储路径,NS_DESIGNATED_INITIALIZER提示为设计初始化方法,UNAVAILABLE_ATTRIBUTE定义为未实现方法,关于这两种宏定义都存在于系统框架中

- (instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER;
- (instancetype)init UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new UNAVAILABLE_ATTRIBUTE;

最终构造函数如下所示:包含了硬盘缓存和内存缓存

- (instancetype)initWithPath:(NSString *)path {
if (path.length == 0) return nil;
YYDiskCache *diskCache = [[YYDiskCache alloc] initWithPath:path];
if (!diskCache) return nil;
NSString *name = [path lastPathComponent];
YYMemoryCache *memoryCache = [YYMemoryCache new];
memoryCache.name = name;
self = [super init];
_name = name;
_diskCache = diskCache;
_memoryCache = memoryCache;
return self;
}

对于YYCache所设计方法,所做操作本质上来说就是增删改查,内部本质是对YYDiskCache和YYMemoryCache的操作,由于读取效率的问题,读取时先有内存缓存中读取,若没有则由硬盘缓存中读取(再存入内存缓存中)

- (BOOL)containsObjectForKey:(NSString *)key
- (void)containsObjectForKey:(NSString *)key withBlock:(void(^)(NSString *key, BOOL contains))block
- (id<NSCoding>)objectForKey:(NSString *)key
- (void)objectForKey:(NSString *)key withBlock:(void(^)(NSString *key, id<NSCoding> object))block
- (void)setObject:(id<NSCoding>)object forKey:(NSString *)key
- (void)setObject:(id<NSCoding>)object forKey:(NSString *)key withBlock:(void(^)(void))block
- (void)removeObjectForKey:(NSString *)key
- (void)removeObjectForKey:(NSString *)key withBlock:(void(^)(NSString *key))block
- (void)removeAllObjects
- (void)removeAllObjectsWithBlock:(void(^)(void))block
- (void)removeAllObjectsWithProgressBlock:(void(^)(int removedCount, int totalCount))progress
endBlock:(void(^)(BOOL error))end

YYMemoryCache和YYDiskCache

为了方便理解和YYCache对YYDiskCache和YYMemoryCache的操作,两类的通用接口设计如下

- (BOOL)containsObjectForKey:(id)key
- (id)objectForKey:(id)key
- (void)setObject:(id)object forKey:(id)key
- (void)setObject:(id)object forKey:(id)key withCost:(NSUInteger)cost
- (void)removeObjectForKey:(id)key
- (void)removeAllObjects

在YYDiskCache则包含了YYCache中所有的接口设计

YYMemoryCache

主要成员变量

  1. pthread_mutex_t(保证线程安全)

  2. _YYLinkedMap自定义类(主包含数据映射字典和链表(根据LRU算法计算自动移除的节点))

  3. dispatch_queue_t操作队列(保证线程不阻塞)

    其中YYLinkeedMap包含了如下成员变量--LRU算法:常使用节点被移动到头结点,即经常使用的节点靠前越靠后就为越不常使用的节点具体实现可查看类中的insertNodeAtHead和bringNodeToHead方法

    CFMutableDictionaryRef _dic; // 字典内 存放对应的缓存数据

    NSUInteger _totalCost;

    NSUInteger _totalCount;

    _YYLinkedMapNode *_head; // 头结点

    _YYLinkedMapNode *_tail; // 尾节点,利用LRU算法实现

    BOOL _releaseOnMainThread;

    BOOL _releaseAsynchronously;

YYDiskCache

主要成员变量

  1. YYKVStorage *_kv; //硬盘存储主要类(线程不安全)
  2. dispatch_semaphore_t _lock;
  3. dispatch_queue_t _queue;

    在YYDiskCache中所做的操作都是基于YYKVStorage的操作,只是增加了信号量上锁以保证线程安全

YYKVStorage

此类主要是利用sqlite3和数据库打交道,当然对于比较大型的文件是直接使用系统的write方法来进行文件保存,这样能更大限度的提升效率。在YYKVStorage的存储中都是以对象的方式进行存储,其对象封装为YYKVStorageItem其中的字段设计如下

key                 text,
filename text,
size integer,
inline_data blob,
modification_time integer,
last_access_time integer,
extended_data blob,
primary key(key)

剩下的就是YYKVStorage如何利用sqlite3进行数据的访问,关于sqlite3的操作就不详述了。

以上便是整个YYCache设计的主要思路,当然里面包含了其他的一些东西。以笔者目前的功力还不能吃透,其中便是YYDispatchQueuePool,在这里YYCache中利用了自己设计的队列池来进行管理。由于没有这方面的经验和时间来学习。这一块就算留作以后研究的一个点吧。

最后贴上YY大神关于自己YYCache的设计思路链接

YYCache设计思路及源码学习的更多相关文章

  1. asp.net abp模块化开发之通用树2:设计思路及源码解析

    一.前言 上一篇大概说了下abp通用树形模块如何使用,本篇主要分析下设计思路. 日常开发中会用到很多树状结构的数据,比如:产品的多级分类.省市区县,大多数系统也会用到类似“通用字典/数据字典”的功能, ...

  2. CopyOnWriteArrayList设计思路与源码分析

    CopyOnWriteArrayList实现了List接口,RandomAccess,Cloneable,Serializable接口. CopyOnWriteArrayList特性 1.线程安全,在 ...

  3. 【 js 基础 】【 源码学习 】源码设计 (持续更新)

    学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析第二部分:undersc ...

  4. 【 js 基础 】【 源码学习 】源码设计 (更新了backbone分析)

    学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析 第二部分:unders ...

  5. Java开源生鲜电商平台-性能优化以及服务器优化的设计与架构(源码可下载)

    Java开源生鲜电商平台-性能优化以及服务器优化的设计与架构(源码可下载) 说明:Java开源生鲜电商平台-性能优化以及服务器优化的设计与架构,我采用以下三种维度来讲解 1.  代码层面. 2.  数 ...

  6. Vue2.1.7源码学习

    原本文章的名字叫做<源码解析>,不过后来想想,还是用“源码学习”来的合适一点,在没有彻底掌握源码中的每一个字母之前,“解析”就有点标题党了.建议在看这篇文章之前,最好打开2.1.7的源码对 ...

  7. JDK源码学习笔记——Integer

    一.类定义 public final class Integer extends Number implements Comparable<Integer> 二.属性 private fi ...

  8. Vue.js 源码学习笔记

    最近饶有兴致的又把最新版 Vue.js 的源码学习了一下,觉得真心不错,个人觉得 Vue.js 的代码非常之优雅而且精辟,作者本身可能无 (bu) 意 (xie) 提及这些.那么,就让我来吧:) 程序 ...

  9. spring源码学习之AOP(一)

    继续源码学习,看了spring中基础的容器和AOP感觉自己也没有什么长进,哈哈,我也不知道到底有用没有,这可能是培养自己的一种精神吧,不管那么多,继续学习!AOP中 AOP中几个重要的概念:(1)Ad ...

随机推荐

  1. 我的第二个FluentNHibernate例子with Knockout

    在上一篇我的第一个FluentNHibernate例子的基础上,我们用上knockoutjs 1用nuget添加knockoutjs包 2用nuget添加json.net包 3..在Index.csh ...

  2. 存储过程中的output跟return区别及实例说明

    存储过程return,表示该存储过程执行到当当前return位置,不再向下执行: 存储过程写法:set ANSI_NULLS ON set QUOTED_IDENTIFIER ON GO ALTER ...

  3. Android系统调用

    android 中intent是经常要用到的.不管是页面牵转,还是传递数据,或是调用外部程序,系统功能都要用到intent. 在做了一些intent的例子之后,整理了一下intent,希望对大家有用. ...

  4. NDK开发历程(一):android native code的调试方法

    引用:http://www.cnblogs.com/ychellboy/archive/2013/02/22/2922683.html 使用NDK在android上做开发是一件“痛并快乐着”的差事,之 ...

  5. 用于svn添加当前目录下所有未追踪的文件,和删除所有手动删除的文件的脚本

    由于要经常用到类似与 git 中的 git add --all 这种操作,但是发现svn中并不支持类似的操作. 虽然可以使用 wildcard 进行匹配,但是 wildcard是在shell中进行匹配 ...

  6. Java多线程线程学习(一)

    一.操作系统级别的进程与线程1.进程: 一个计算机程序的运行实例.包含了需要执行的指令,有自己的独立地址空间,是互相隔离的.进程拥有各种资源和状态信息,包括打开的文件.子进程和信号处理.2.线程: 表 ...

  7. failed to lazily initialize a collection of role:XXX, no sessi

    系统 框架  springMVC+hibernate 这种情况 由于 hibernate 的 懒汉机制,和 Spring 事务机制(不确定)造成的 由于 spring 配置的时候,在service 层 ...

  8. WPF、Sivelright、UWP

    Sivelright:  http://www.cnblogs.com/webabcd/category/106371.html UWP 律师查询 MVVM WPF入门教程系列一——基础 WPF入门教 ...

  9. vc6 使用的那些事

    VC6.0中Release下调试模式设置 http://blog.csdn.net/wangqinghao/article/details/7730428

  10. DataGridView

    一.实现CheckBox列. 1.1 增加CheckBox列: 在DataGridView中增加CheckBox列: 注意:设置ColumnType类型和设置FalseValue为0,TrueValu ...