【发布时间】:2015-01-16 21:34:35
【问题描述】:
我相信我理解 Future/Callable 的工作原理。就像下面的代码(第 2 节)一样,cacheLoader1 和 cacheLoader2 是 Callable 实现的两个实例,它的 call() 方法是加载一个缓存
@Override
public Cache call() throws Exception {
cache.loadCache();
return cache;
}
我打算使用两个线程来运行任务并合并返回的缓存。我了解 future#get() 将阻塞,直到相应的线程完成。但是,我遇到的问题是它永远不会返回。我注释掉了 Future#get() 的单行,它继续进行。
我查看了 cache#loadCache() 中的代码,发现它尝试从 DB 表中检索数据,例如 service.getData(),在它下面调用 DAO,而 DAO 又使用 Spring 的 getSqlMapClientTemplate 和 iBatis SQL。如果我恢复注释的 Future#get,DAO 将永远不会返回。
List<Future<Cache>> list = new ArrayList<Future<Cache>>();
Future<Cache> f = es.submit(cacheLoader1);
list.add(f);
f = es.submit(cacheLoader2);
list.add(f);
for(Future<Cache> future: list){
logger.debug("done with {}",future.get());
}
我很难理解可能出了什么问题。有什么帮助吗?是因为调用方法中的 throws Exception 子句吗?
附言进一步澄清:
ExecutorService es = Executors.newFixedThreadPool(2);
class CacheLoader implements Callable<Cache>{
....
@Override
public Cache call() throws Exception {
cache.loadCache();
return cache;
}
}
CacheLoader cacheLoader1, cacheLoader2;
更新:
我似乎找到了根本原因,但需要建议最好的解决方案是什么。首先我很抱歉,早期的信息不足以让人们查明问题。
这是一个 Spring 项目,第二部分中的代码位于一个名为“init”的 bean 的 init-method 中。前面提到的 DAO 也是在 Spring 中注册的。所以问题似乎是方法“init”正在挂起块 f.get() 的 bcoz 并且 Spring config 无法完成;它是一种循环依赖吗?我还没有找到最好的方法...
谢谢,
乔恩
【问题讨论】:
-
什么是
es?cacheLoader1是什么? -
@Sam:请查看新编辑的内容。谢谢。
-
这一定是对
cache.loadCache();的调用中的某些内容 - 尝试用虚拟打印语句替换该调用以查看它是否完成。如果您的打印语句有效,那么loadCache()中的某些内容正在挂起。 -
这似乎应该有效。如果在代码中调用cacheLoader1.call()而不是提交给Executor,是否有效?
-
请看我的更新,谢谢!
标签: java concurrency future callable