如何使执行程序服务等到所有线程完成

时间:2014-05-21 19:35:28

标签: future executorservice

我使用执行程序服务启动多个线程以向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());
    }

我在(!future.isDone())块中看到了一些例外情况。如何在执行器服务关闭时确保每个未来都完成?

1 个答案:

答案 0 :(得分:0)

我喜欢使用倒计时锁定器。

将锁存器设置为您正在迭代的大小,并将该锁存器传递给您的callables,然后在run / call方法中有一个try / finally块,递减倒计时锁存器。

将所有内容排入您的执行程序服务之后,只需调用latch的await方法,该方法将阻塞,直到完成所有操作。那时你所有的callables都将完成,你可以正确地关闭你的执行者服务。

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