2014-05-21 108 views
1

我使用executor服务来启动多个线程来发送请求到api并获取数据。有时我看到一些线程还没有完成他们的工作,服务已经杀死了那个线程,我如何强制服务等待线程完成他们的工作?如何使执行器服务等到所有线程完成

这里是我的代码:

 ExecutorService pool = Executors.newFixedThreadPool(10); 
     List<Future<List<Book>>> futures = Lists.newArrayList(); 
     final ObjectMapper mapper1 = new ObjectMapper(); 
     for (final Author a : authors) { 
      futures.add(pool.submit(new Callable<List<Book>>() { 
       @Override 
       public List<Book> call() throws Exception { 
        String urlStr = "http://localhost/api/book?limit=5000&authorId=" + a.getId(); 

        List<JsonBook> Jsbooks = mapper1.readValue(
          new URL(urlStr), BOOK_LIST_TYPE_REFERENCE); 

        List<Book> books = Lists.newArrayList(); 
        for (JsonBook jsonBook : Jsbooks) { 
         books.add(jsonBook.toAvro()); 
        } 

        return books; 
       } 
      })); 
     } 
     pool.shutdown(); 
     pool.awaitTermination(3, TimeUnit.MINUTES); 

     List<Book> bookList = Lists.newArrayList(); 
    for (Future<List<Book>> future : futures) { 
     if (!future.isDone()) { 
      LogUtil.info("future " + future.toString()); <-- future not finished yet 
      throw new RuntimeException("Future to retrieve books: " + future + " did not complete"); 

} 
     bookList.addAll(future.get()); 
    } 

,我看到一些excepitons在块(的Future.isDone()!)。我如何确保执行器服务关闭时每个将来都完成?

+0

可能重复[如何等待所有线程完成,使用ExecutorService?](http://stackoverflow.com/questions/1250643/how-to-wait-for-all-threads-to-finish -using-executorservice) – Ray

+0

有什么例外?看起来像'未来'正在完成,但在api调用中有一个例外。 – tariksbl

回答

0

我喜欢使用倒数锁存器。

将锁存器设置为您正在迭代的大小并将该锁存器传递到您的可调用函数中,然后在run/call方法中有一个try/finally块来递减倒计数锁存器。

当所有事情都被排队到你的执行器服务之后,只需调用你的latch的await方法,它将阻塞,直到完成。那时你的所有可调用卡都将完成,你可以正确关闭你的执行者服务。

此链接有一个如何设置它的例子。 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html