2014-05-21 107 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