(Java)缓存的分为文件缓存或磁盘缓存(disc cache)和内存缓存(memory cache)两种;文件缓存就是把数据存储在本地磁盘上,内存缓存一般是一个map.缓存的作用就是把首次从网络的获取数据保存起来,当再次訪问的时候能够直接从缓存中获取数据而不是从网络中又一次载入。能够降低系统开销。提高响应速度。

单独使用内存缓存和单独使用文件缓存应用的运行流程例如以下所看到的:

内存缓存和文件缓存同一时候使用的情况下的流程图大致例如以下所看到的:

须要注意的是,当从网络载入数据的时候用一个线程或者提供一个线程池来完毕这个功能是比較好的选择。同一时候须要注意的是因为获取数据的方法须要返回值,依据上面的流程图可知返回的数据的途径能够模拟一个包括了磁盘缓存和内存缓存的实现方案。

public class CacheDemo {
	private ExecutorService pool = Executors.newFixedThreadPool(6);
	private HashMap<String, SoftReference<Data>> memoryCache;// 内存缓存
	public CacheDemo(int imageSaveCount, Data defaultData) {
		memoryCache = new HashMap<String, SoftReference<Data>>();
	}
	/**
	 * 载入数据
	 * @param saveFolder
	 *            文件缓存的路径
	 * @param dataUrl
	 *            数据的地址
	 * @return
	 */
	Path path = null;
	public Data loadData(String saveFolder, final String dataUrl)
			throws InterruptedException, ExecutionException {
		// 推断缓存中是否有数据
		if (memoryCache.containsKey(dataUrl)) {
			SoftReference<Data> 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<Data> soft = new SoftReference<Data>(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;
	}
}


posted on 2017-08-02 12:10  yutingliuyl  阅读(156)  评论(0编辑  收藏  举报