(Java)缓存的分为文件缓存或磁盘缓存(disc cache)和内存缓存(memory cache)两种;文件缓存就是把数据存储在本地磁盘上,内存缓存通常是一个map.缓存的作用就是把首次从网络的获取数据保存起来,当再次访问的时候可以直接从缓存中获取数据而不是从网络中重新加载。可以减少系统开销,提高响应速度。
单独使用内存缓存和单独使用文件缓存应用的执行流程如下所示:
内存缓存和文件缓存同时使用的情况下的流程图大致如下所示:
需要注意的是,当从网络加载数据的时候用一个线程或者提供一个线程池来完成这个功能是比较好的选择。同时需要注意的是由于获取数据的方法需要返回值,根据上面的流程图可知返回的数据的途径可以模拟一个包含了磁盘缓存和内存缓存的实现方案。
public class CacheDemo {
private ExecutorService pool = Executors.newFixedThreadPool(6);
private HashMap memoryCache;// 内存缓存
public CacheDemo(int imageSaveCount, Data defaultData) {
memoryCache = new HashMap();
}
/**
* 加载数据
* @param saveFolder
* 文件缓存的路径
* @param dataUrl
* 数据的地址
* @return
*/
Path path = null;
public Data loadData(String saveFolder, final String dataUrl)
throws InterruptedException, ExecutionException {
// 判断缓存中是否有数据
if (memoryCache.containsKey(dataUrl)) {
SoftReference softReference = memoryCache.get(dataUrl);
if (softReference != null) {
Data data = softReference.get();
if (data != null) {
return data;
}
}
}
// 判断文件缓存中是否有数据
String filename = getFileName(dataUrl);// 截取url中的文件名
final String saveFilepath = saveFolder;// 本地缓存文件的路径
File savePath = new File(saveFilepath);
if (!savePath.exists()) {// 如果没有就创建
savePath.mkdirs();
} else {
File file = new File(saveFilepath + File.separator + filename);
if (file.exists()) {
// 从本地文件中获取数据
Data data = getData(file);
if (data != null)
return data;
}
}
//如果缓存中没有数据,就开启一个callable从网络中获取数据
DataCallable dc = new DataCallable(dataUrl, saveFilepath);
Future future = pool.submit(dc);
return (Data) future.get();
}
/**
* 定义一个任务从,线程中返回数据
*/
class DataCallable implements Callable {
private String dataUrl;
private String saveFilepath;
DataCallable(String dataUrl, String saveFilepath) {
this.dataUrl = dataUrl;
this.saveFilepath = saveFilepath;
}
@Override
public Data call() throws Exception {
byte[] datas = loadDataFromNet(dataUrl);
Data data = null;
if (datas != null) {
data = new Data(datas);
SoftReference soft = new SoftReference(data);
// 数据放入内存缓存
memoryCache.put(dataUrl, soft);
data = null;
}
// 写入文件缓存
try (FileOutputStream out = new FileOutputStream(new File(
saveFilepath))) {
out.write(datas);
}
return data;
}
}
public byte[] loadDataFromNet(String url) {
InputStream inputStream = null;
// Bitmap bitmap = null;
try {
URL m = new URL(url);
HttpURLConnection hURL = (HttpURLConnection) m.openConnection();
hURL.setConnectTimeout(5000);
hURL.setReadTimeout(5000);
inputStream = (InputStream) hURL.getInputStream();
int len = inputStream.available();
byte[] data = new byte[1024 * 15];
ByteArrayOutputStream bStream = new ByteArrayOutputStream();
int size = 0;
while ((len = inputStream.read(data)) != -1) {
bStream.write(data, 0, len);
size += len;
}
data = bStream.toByteArray();
bStream.reset();
return data;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
public static String getFileName(String filePath) {
return filePath.substring(filePath.lastIndexOf(File.separator) + 1);
}
public static Data getData(File file) {
FileInputStream fis = null;
Data data = null;
try {
if (file.isDirectory()) {
return null;
}
file.setLastModified(System.currentTimeMillis());
fis = new FileInputStream(file);
data = new Data();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (OutOfMemoryError e) {
e.printStackTrace();
} finally {
try {
fis.close();
} catch (Exception e) {
}
}
return data;
}
}