簡體   English   中英

如何讓主線程在ThreadPoolExecutor中等待其他線程完成

[英]How to make the main thread wait for the other threads to complete in ThreadPoolExecutor

我正在使用ThreadPoolExecutor在我的Java應用程序中實現線程。

我有一個XML,我需要解析並將其的每個節點添加到一個線程來執行完成。 我的實現是這樣的:

parse_tp是一個創建的線程池對象,ParseQuotesXML是帶有run方法的類。

        try {     
           List children = root.getChildren();               
        Iterator iter = children.iterator();

        //Parsing the XML     
        while(iter.hasNext()) {       
           Element child = (Element) iter.next();           
           ParseQuotesXML quote = new ParseQuotesXML(child, this);         
           parse_tp.execute(quote);         
        }
    System.out.println("Print it after all the threads have completed");
        catch(Exception ex) {  
        ex.printStackTrace();      
        }
        finally {  
    System.out.println("Print it in the end.");
if(!parse_tp.isShutdown()) {
                if(parse_tp.getActiveCount() == 0 && parse_tp.getQueue().size() == 0 ) {
                    parse_tp.shutdown();                    
                } else {
                    try {
                        parse_tp.awaitTermination(30, TimeUnit.SECONDS);
                    } catch (InterruptedException ex) {
                        log.info("Exception while terminating the threadpool "+ex.getMessage());
                        ex.printStackTrace();
                    }
                }
            }
          parse_tp.shutdown();  
        }

問題是,在其他線程退出之前打印兩個打印輸出語句。 我想讓主線程等待所有其他線程完成。 在正常的Thread實現中,我可以使用join()函數來完成它,但是沒有辦法在ThreadPool Executor中實現相同的功能。 還想問一下,在finally塊中編寫的代碼是否能正確關閉threadpool?

謝謝,阿米特

CountDownLatch就是為此目的而設計的。 可以在此處此處找到示例。 如果事先不知道線程數,請考慮使用Phaser ,Java 1.7中的新增功能或UpDownLatch

為了回答你的第二個問題,我認為你正在做一個合理的工作,試圖清理你的線程池。

關於你的第一個問題,我認為你想要使用的方法是提交而不是execute 而不是嘗試在文本中解釋所有內容,這里是我編寫的單元測試中編輯的片段,它創建了許多任務,每個都執行完整工作的一部分,然后在起點處回過頭來添加結果:

final AtomicInteger messagesReceived = new AtomicInteger(0);

// ThreadedListenerAdapter is the class that I'm testing 
// It's not germane to the question other than as a target for a thread pool.
final ThreadedListenerAdapter<Integer> adapter = 
    new ThreadedListenerAdapter<Integer>(listener);
int taskCount = 10;

List<FutureTask<Integer>> taskList = new ArrayList<FutureTask<Integer>>();

for (int whichTask = 0; whichTask < taskCount; whichTask++) {
    FutureTask<Integer> futureTask = 
        new FutureTask<Integer>(new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
            // Does useful work that affects messagesSent
            return messagesSent;
        }
    });
    taskList.add(futureTask);
}

for (FutureTask<Integer> task : taskList) {
    LocalExecutorService.getExecutorService().submit(task);
}

for (FutureTask<Integer> task : taskList) {
    int result = 0;
    try {
        result = task.get();
    } catch (InterruptedException ex) {
        Thread.currentThread().interrupt();
    } catch (ExecutionException ex) {
        throw new RuntimeException("ExecutionException in task " + task, ex);
    }
    assertEquals(maxMessages, result);
}

int messagesSent = taskCount * maxMessages;
assertEquals(messagesSent, messagesReceived.intValue());

我認為這個片段與你想要做的類似。 關鍵組件是submitget方法。

首先,您可以使用ThreadPoolExecutor.submit()方法,它返回Future實例,然后在您提交所有工作項后,您可以通過這些期貨進行迭代,並在每個工作項上調用Future.get()

或者,您可以使用ThreadPoolExecutor.invokeAll()一次性准備可運行的工作項並一次提交它們,這將等待所有工作項完成,然后您可以獲得執行結果或異常調用相同的Future.get()方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM