使用Java的Future / Callable时的一个奇怪问题

时间:2015-01-16 21:34:36

标签: java concurrency future callable

我相信我理解Future / Callable如何运作良好。与下面的代码(第2部分)类似,cacheLoader1和cacheLoader2是Callable实现的两个实例,其call()方法是加载缓存

@Override
public Cache call() throws Exception {
  cache.loadCache();
  return cache;
}

我打算使用两个线程来运行任务并合并返回的缓存。我理解未来#get()将阻塞,直到相应的线程完成。然而,我遇到的问题是永远不会回来。我注释掉了Future#get()的单行,然后就继续了。

我查看了缓存#loadCache()中的代码,发现它尝试从DB表中检索数据,比如service.getData(),在它下面调用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());
}

我很难理解可能出错的地方。有帮助吗?那是因为在调用方法中抛出了Exception子句吗?

P.S。进一步澄清:

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-method 中,名为&#34; init &#34;一个豆子。上述DAO也在Spring注册。所以问题似乎是方法&#34; init&#34;正在挂起块f.get()的bcoz并且Spring配置无法完成;它是一种循环依赖吗?我仍然没有找到最佳方法......

谢谢,

乔恩

1 个答案:

答案 0 :(得分:0)

我找到了解决方案,很容易。

在init-method中,我创建了另一个线程,如下面的

ExecutorService es = Executors.newFixedThreadPool(2);
es.execute(cacheLoader);

和CacheLoader实现Runnable( es1 是ExecuteService的另一个实例):

public class CacheLoader implements Runnable{
  public void run() {
    Future<Cache> f1 = es1.submit(new Callable<Cache>(){
        @Override
        public Cache call(){
            cache1.loadCache();
            return cache1;
        }
    });

    Future<Cache> f2 = es1.submit(new Callable<Cache>(){
        @Override
        public Cache call(){
            cache2.loadCache();
            return cache2;
        }
    });
    Cache c1 = f1.get();
    Cache c2 = f2.get();
  } //~end of run() ~
}