在前两篇文章中我们详细的介绍了okhttp缓存文件的结构,缓存的详细读写过程以及缓存文件的清理机制,今天,我们大致介绍下缓存文件最复杂也是最容易出错的部分:并发控制
涉及的所有文件
在开始之前,我们先分析下整个okhttp缓存过程中涉及到了哪些文件:
文件名称 | 何时创建 | 何时写入 | 何时读取 | 何时销毁 |
---|---|---|---|---|
journal | 初始化时 | 初始化时写入5行头部; 缓存写入,读取,删除 |
初始化时 | 不会销毁,会在重建时被新文件替换 |
journal.tmp | 重建journal文件时 | 重建journal文件时 | 只会替换成journal,不会直接读取 | 重建journal文件完成后被删除 |
journal.bkp | 重建journal文件时,原有journal重命名成.bkp文件 | 无 | 无 | 重建journal文件完成时;初始化时 |
xxxx.0.tmp | 缓存Header写入时 | cache的put执行时 | 只会替换成xxx.0文件,不会读取 | put执行完成后会重命名成xxx.0 |
xxxx.0 | Cache put完成后原有的xxxx.0.tmp重命名成 | 不会直接写入 | 调用Cache的get方法时 | 压缩journal文件时;删除某个请求的缓存时;缓存完毕时被其他.0.tmp替换 |
XXX.1.tmp | 缓存body时创建 | 读取body信息时顺便复制数据写入 | 只会替换成XXX.1文件,不会直接读取 | body缓存完毕后会删除 |
xxx.1 | body读取最后close的时候原有的xxx.1.tmp重命名成 | 不会直接写入 | 缓存调用get时获取一个body,该Body读取时 | 压缩journal文件时;删除某个请求的缓存时;缓存完毕时被其他.0.tmp替换 |
如何防止同时创建文件
靠synchronized关键字保证
如何防止写入冲突
靠synchronized关键字保证
如何防止读写冲突
所有文件的写入操作都是写到一个文件的.tmp临时文件中,这个时候读还是从原来的文件读,写入不会污染原来文件,写入完成后会将.tmp文件替换掉原有文件,这样完美解决读写冲突。
如何防止删除和读写冲突
其实对于缓存来说,文件的可靠性要求不是很高,缓存失效的情况下,我们不使用缓存,直接从网络获取就可以了。正是基于这种思想,okhttp并不存在在删除时检查是否有线程正在写入或读取的行为,而是直接删除,在读写时做好容错处理,对被破坏的数据直接丢弃,转而从网络请求获取数据。
网友评论