FutureTask在缓存中使用

缓存主要做用是提升应用程序吞吐量和响应性,固然也有负面影响,占用更多内存。在设计SqlTemplate也有个简单的本地缓存,sql模板实际只须要解释一次就能够了,之后的调用复用以前解释过。开始的时候是使用简单的HashMap实现的,可是在并发状况下会出现重复解释,下面是初版的代码片断。 java

public class Configuration {

	private ConcurrentHashMap<String, SqlTemplate > templateCache;
    ......

	public SqlTemplate getTemplate(final String content) {
		if (cacheTemplate) { //是 不然缓存模板

			SqlTemplate sqlTemplate = templateCache.get(content);
			  
	        if (sqlTemplate != null){
	    	   sqlTemplate  = createTemplate(content) ;
	    	   
	    	   templateCache.put(content, sqlTemplate) ;
	        }
	        return sqlTemplate;
		}
		return createTemplate(content);
	}
        //解释构建模板对象
	private SqlTemplate createTemplate(String content) {
		SqlTemplate template = new SqlTemplate.SqlTemplateBuilder(this, content)
				.build();
		return template;
	}
	......
}

经过看上面的代码,很容易发现问题的所在,一个线进createTemplate解释模板,其余线程不知道这个模板已经在解释中,因此可能会出现同sql模板会出现屡次计算。理想的状况下其余线程知道模板在解释中,只需等待完成。下面是使用FutureTask改进后的第二版本代码,看似很完美^_^。 sql

public class Configuration {

	private ConcurrentHashMap<String, FutureTask<SqlTemplate>> templateCache;

......

	public SqlTemplate getTemplate(final String content) {

		if (cacheTemplate) {////是 不然缓存模板

			FutureTask<SqlTemplate> f = templateCache.get(content);

			if (f == null) {
				FutureTask<SqlTemplate> ft = new FutureTask<SqlTemplate>(
						new Callable<SqlTemplate>() {

							public SqlTemplate call() throws Exception {
								return createTemplate(content);
							}
						});

				f = templateCache.putIfAbsent(content, ft);

				if (f == null) {
					ft.run();
					f = ft;
				}
			}

			try {
				return f.get();
			} catch (Exception e) {
				templateCache.remove(content); //防止缓存污染
				throw new RuntimeException(e);
			}

		}

		return createTemplate(content);

	}

    //解释构建模板对象
	private SqlTemplate createTemplate(String content) {
		SqlTemplate template = new SqlTemplate.SqlTemplateBuilder(this, content)
				.build();
		return template;
	}

......
}


第二版解决了初版的缺陷(重复解释),并发性也不错,能很好返回已经解释过的结果。此次缓存不是结果值,而是一个FutureTask,关于Future详细使用请参考啊了个里写的《Java 并发之 Future 接口。关于SqlTemplate请参考http://my.oschina.net/u/866190/blog/175800 缓存

相关文章
相关标签/搜索