Future.get()不会返回

时间:2012-12-20 12:03:02

标签: java multithreading concurrency

我有以下代码:

public class Test {
   List<Future> future = new ArrayList<Future>();

   public static void main(String args[]) throws Exception {

     Adapter b1 = new Adapter();
     final ExecutorService threadPool = Executors.newCachedThreadPool();

      for(//iterate for number of files) {  
         while(data exists in file) {
            //Call a function to process and update values in db 
            future.add(threadPool.submit(new Xyz(b1)));
            //read next set of data in file;
         }
       }

      try {
         for(Future f: future) { 
            f.get(); 
         }
      }
      catch(Exception e) {
         throw e;
      }    
   }
}

class Xyz implements Runnable {
   private Adapter a1;

   public Xyz(Adapter al) {
      this.a1=a1;
   }

   @Override
   public void run() {
      try { 
         a1.abc();
      } catch (Exception e) {
          throw new RuntimeException(e);
      } 
   }
}

当文件数为1(循环运行1次)时,代码运行正常。

但是,当文件数量增加时,代码永远不会从future.get()方法返回。

2 个答案:

答案 0 :(得分:1)

  只是出于好奇......我需要在某处关闭执行程序吗?

是的,这可能就是问题所在。每个Future.get()将阻塞,直到相应的任务完成,然后一旦所有任务完成,您的main线程将退出。但是你的java进程将退出,因为线程池线程在后台仍处于活动状态。完成后应该关闭执行程序,这很可能是main方法中的最后一个。

我还注意到你提交的许多任务都包含了相同的 Adapter实例并且都调用了它的abc()方法 - 检查那里是否有任何会死锁的内容当在多个线程中同时调用时。

答案 1 :(得分:0)

您的Callable::call / Runable::run未返回。否则相应的未来不会阻止。

额外的executor.shutdown或future.cancel会让InterruptedException停止处理您提交的对象的线程,但如果要抓住它,则取决于您。您有责任使您提交的工作停止。

当您向CachedExecutor提交数千个Callables / Runnables时,它可能会产生如此多的线程,导致您的机器变得如此之慢以至于您认为它需要永远。但你会注意到这一点。

当处理未定义数量的可并行化任务时,我建议使用FixedThreadPool而不是更多的线程存在cpu核心。

编辑:因此,当您在a1.abc();设置断点并向前迈出一步时,您可能会发现它永远不会返回。