[英]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());
首先,您可以使用ThreadPoolExecutor.submit()方法,它返回Future實例,然后在您提交所有工作項后,您可以通過這些期貨進行迭代,並在每個工作項上調用Future.get() 。
或者,您可以使用ThreadPoolExecutor.invokeAll()一次性准備可運行的工作項並一次提交它們,這將等待所有工作項完成,然后您可以獲得執行結果或異常調用相同的Future.get()方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.