Java 我如何暂停 main() 直到所有其他线程都死了?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2436142/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I pause main() until all other threads have died?
提问by ericso
In my program, I am creating several threads in the main() method. The last line in the main method is a call to System.out.println(), which I don't want to call until all the threads have died. I have tried calling Thread.join() on each thread however that blocks each thread so that they execute sequentially instead of in parallel.
在我的程序中,我在 main() 方法中创建了几个线程。main 方法中的最后一行是对 System.out.println() 的调用,我不想在所有线程都死之前调用它。我曾尝试在每个线程上调用 Thread.join() ,但是它会阻塞每个线程,以便它们按顺序执行而不是并行执行。
Is there a way to block the main() thread until all other threads have finished executing? Here is the relevant part of my code:
有没有办法阻塞 main() 线程,直到所有其他线程完成执行?这是我的代码的相关部分:
public static void main(String[] args) {
//some other initialization code
//Make array of Thread objects
Thread[] racecars = new Thread[numberOfRaceCars];
//Fill array with RaceCar objects
for(int i=0; i<numberOfRaceCars; i++) {
racecars[i] = new RaceCar(laps, args[i]);
}
//Call start() on each Thread
for(int i=0; i<numberOfRaceCars; i++) {
racecars[i].start();
try {
racecars[i].join(); //This is where I tried to using join()
//It just blocks all other threads until the current
//thread finishes.
} catch(InterruptedException e) {
e.printStackTrace();
}
}
//This is the line I want to execute after all other Threads have finished
System.out.println("It's Over!");
}
Thanks for the help guys!
感谢您的帮助!
Eric
埃里克
采纳答案by middus
You start your threads and immediately wait for them to be finished (using join()
). Instead, you should do the join()
outside of the for-loop in another for-loop, e.g.:
您启动线程并立即等待它们完成(使用join()
)。相反,您应该join()
在另一个 for 循环中执行 for 循环的外部,例如:
// start all threads
for(int i=0; i<numberOfRaceCars; i++) {
racecars[i].start();
}
// threads run... we could yield explicity to allow the other threads to execute
// before we move on, all threads have to finish
for(int i=0; i<numberOfRaceCars; i++) {
racecars[i].join(); // TODO Exception handling
}
// now we can print
System.out.println("It's over!");
回答by Thomas
You could wait()
in your main thread and have all threads issue a notifyAll()
when they're done. Then each time your main thread gets woken up that way, it can check if there's at least one thread that's still alive in which case you wait()
some more.
您可以wait()
在主线程中并让所有线程notifyAll()
在完成后发出 a 。然后每次你的主线程以这种方式被唤醒时,它可以检查是否至少有一个线程仍然活着,在这种情况下你会wait()
更多。
回答by Smalltown2k
You could make the last line be in a "monitoring" thread. It would check every so often that it is the only running thread and some completion state == true
and then could fire if it was. Then it could do other things than just println
您可以将最后一行放在“监视”线程中。它会经常检查它是否是唯一正在运行的线程和一些完成状态== true
,如果是,则可以触发。然后它可以做其他事情,而不仅仅是println
回答by the-banana-king
You could share a CyclicBarrier
object among your RaceCar
s and your main thread, and have the RaceCar
threads invoke await()
as soon as they are done with their task. Construct the barrier with the number of RaceCar
threads plus one (for the main thread). The main thread will proceed when all RaceCar
s have finished.
See http://java.sun.com/javase/6/docs/api/java/util/concurrent/CyclicBarrier.html
您可以CyclicBarrier
在RaceCar
s 和主线程之间共享一个对象,并在RaceCar
线程await()
完成任务后立即调用它们。用RaceCar
线程数加一(对于主线程)构造屏障。当所有RaceCar
s 完成后,主线程将继续进行。见http://java.sun.com/javase/6/docs/api/java/util/concurrent/CyclicBarrier.html
In detail, construct a CyclicBarrier
in the main thread, and add a barrier.await()
call in your RaceCar
class just before the run()
method exits, also add a barrier.await()
call before the System.out.println()
call in your main thread.
具体来说,CyclicBarrier
在主线程中构造一个,并在方法退出之前barrier.await()
在您的RaceCar
类中run()
添加一个barrier.await()
调用,并System.out.println()
在您的主线程中的调用之前添加一个调用。
回答by Peter Lawrey
You can add a shutdown hook for the "Its Over" message. This way it will be produced when the program finishes and you don't have to wait for each thread.
您可以为“Its Over”消息添加关闭挂钩。这样它就会在程序完成时产生,你不必等待每个线程。
回答by Tomá? ?urina
Simplest way
最简单的方法
while (Thread.activeCount() > 1) {
}
I know it block main thread... but it works perfectly!
我知道它会阻塞主线程......但它工作得很好!
回答by user1668782
Try This example:
试试这个例子:
public class JoinTest extends Thread {
public static void main(String[] args)
{
JoinTest t = new JoinTest();
t.start();
try {
t.join();
int i = 0;
while(i<5)
{
System.out.println("parent thread is running......" +i++);
}
} catch (Exception e) {
// TODO: handle exception
}
}
public void run()
{
try {
int i =0;
while(i<5)
{
System.out.println("child thread running ........." +i++);
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
回答by Ravindra babu
You have better options if you go for ExecutorServiceor ThreadPoolExecutorframework.
如果您选择ExecutorService或ThreadPoolExecutor框架,您将有更好的选择。
Executes the given tasks, returning a list of Futures holding their status and results when all complete. Future.isDone() is true for each element of the returned list. Note that a completed task could have terminated either normally or by throwing an exception. The results of this method are undefined if the given collection is modified while this operation is in progress. Type Parameters:
CountDownLatch: Initialize CountDownLatch with counter as number of threads. Use
countDown()
andawait()
APIs and wait for counter to become zero.
执行给定的任务,在全部完成后返回保存其状态和结果的 Future 列表。Future.isDone() 对于返回列表的每个元素都为真。请注意,已完成的任务可能已正常终止或通过抛出异常终止。如果在此操作进行时修改了给定的集合,则此方法的结果未定义。类型参数:
CountDownLatch:使用计数器作为线程数初始化 CountDownLatch。使用
countDown()
和await()
API 并等待计数器变为零。
Further references:
进一步参考:
How to use invokeAll() to let all thread pool do their task?
如何使用 invokeAll() 让所有线程池完成他们的任务?