0

我有以下代码:

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 时(for 循环运行 1 次),代码运行良好。

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

4

2 回答 2

1

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

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

我还注意到,您提交的许多任务都包装了同一个 Adapter实例并且都调用了它的abc()方法——检查当在多个线程中同时调用时,那里没有任何东西会死锁。

于 2012-12-20T12:30:57.793 回答
0

您的Callable::call/Runable::run不返回。否则对应的future不会阻塞。

额外的 executor.shutdown 或future.cancelInterruptedException停止处理您提交的对象的线程,但是否捕获它取决于您。您有责任让您提交的作业停止。

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

在处理未定义数量的可并行化任务时,我建议使用FixedThreadPool没有更多线程的 cpu 内核。

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

于 2012-12-20T13:02:47.437 回答