FutureTask在缓存中使用

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

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改进后的第二版本代码,看似很完美^_^。

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


转载于:https://my.oschina.net/u/866190/blog/177021

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值