# OkHttp DiskLruCache(29064)
java.util.NoSuchElementException
1
java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:759)
2
java.util.LinkedHashMap$LinkedValueIterator.next(LinkedHashMap.java:785)
3
okhttp3.internal.cache.DiskLruCache.trimToSize(Unknown Source:18)
4
okhttp3.internal.cache.DiskLruCache$1.run(Unknown Source:25)
5
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
6
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
7
java.lang.Thread.run(Thread.java:919)
项目里边是retrofit+okhttp3 3.14.9
一开始以为是okhttp的bug,查证了一番发现没有作用,重新review代码,发现
OkHttpClient.Builder.cache(Cache cache)
传入的cache并不是单例,也就是说,对于同一缓存目录,只能传入同一个cache对象。否则,如果Retrofit访问的url相同时,会出现多个线程处理同一个缓存文件的情况,在trimToSize的时候,出现多线程问题。
解决方案:
review代码中的调用,保证同一个retrofit对象或者同一缓存目录,使用同一个cache
代码示例
private static Map<String,Cache> cacheHashMap =new ConcurrentHashMap<>();
private Cache initDiskCache(String dir) {
Cache diskCache =null;
if(cacheHashMap.get(dir)!=null){
diskCache = cacheHashMap.get(dir);
return diskCache;
}
Cache diskCache = new Cache(new File(dir), maxCacheSize);
cacheHashMap.put(dir,diskCache);
return diskCache;
}
//代码示意,同一缓存目录或者同一reftrofit保证单例
private void buildOkhttpClient(){
OkHttpClient.Builder builder = new OkHttpClient.Builder();
//此处多为外部存储目录,需要重新看下
builder.cache(initDiskCache(context.getFilesDir().getPath());
}