我使用执行程序服务启动多个线程以向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())块中看到了一些例外情况。如何在执行器服务关闭时确保每个未来都完成?
答案 0 :(得分:0)
我喜欢使用倒计时锁定器。
将锁存器设置为您正在迭代的大小,并将该锁存器传递给您的callables,然后在run / call方法中有一个try / finally块,递减倒计时锁存器。
将所有内容排入您的执行程序服务之后,只需调用latch的await方法,该方法将阻塞,直到完成所有操作。那时你所有的callables都将完成,你可以正确地关闭你的执行者服务。
此链接有一个如何设置的示例。 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html