在我的程序中,我在main()方法中创建了几个线程。 main方法的最后一行是对System.out.println()的调用,在所有线程都死之前我不想调用它。我已经尝试在每个线程上调用Thread.join()但是阻塞每个线程以便它们顺序执行而不是并行执行。
有没有办法阻止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!");
}
感谢帮助人员!
埃里克
答案 0 :(得分:45)
启动线程并立即等待它们完成(使用join()
)。相反,你应该在另一个for循环中执行for循环之外的join()
,例如:
// 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!");
答案 1 :(得分:6)
您可以在CyclicBarrier
和主线程中共享RaceCar
对象,并让RaceCar
个线程在完成任务后立即调用await()
。构造具有RaceCar
个线程数加一个(对于主线程)的数量的屏障。所有RaceCar
完成后,主线程将继续。
见http://java.sun.com/javase/6/docs/api/java/util/concurrent/CyclicBarrier.html
详细信息,在主线程中构建CyclicBarrier
,并在barrier.await()
方法退出之前在RaceCar
类中添加run()
调用,同时添加{ {1}}在主线程barrier.await()
调用之前调用。
答案 2 :(得分:2)
您可以在主线程中wait()
并让所有线程在完成后发出notifyAll()
。然后,每当你的主线程以这种方式唤醒时,它可以检查是否至少有一个仍然存活的线程,在这种情况下你wait()
还有更多。
答案 3 :(得分:1)
您可以使用join方法。请参阅文档here
答案 4 :(得分:1)
您可以为“Over Over”消息添加关闭挂钩。这样,它将在程序完成时生成,您不必等待每个线程。
答案 5 :(得分:1)
如果您选择ExecutorService或ThreadPoolExecutor框架,则有更好的选择。
执行给定的任务,在完成所有任务后返回持有其状态和结果的Futures列表。对于返回列表的每个元素,Future.isDone()都为true。请注意,已完成的任务可能正常终止或通过抛出异常终止。如果在此操作正在进行时修改了给定集合,则此方法的结果是不确定的。 输入参数:
CountDownLatch:使用计数器初始化CountDownLatch作为线程数。使用countDown()
和await()
API并等待计数器变为零。
进一步参考:
How to use invokeAll() to let all thread pool do their task?
答案 6 :(得分:0)
您可以将最后一行放在“监视”主题中。它会经常检查它是唯一正在运行的线程和一些完成状态== true
然后可能会触发它。然后它可以做除println
答案 7 :(得分:0)
最简单的方式
while (Thread.activeCount() > 1) {
}
我知道它会阻止主线程...但它完美无缺!
答案 8 :(得分:0)
试试这个例子:
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
}
}
}