如何暂停main()直到所有其他线程都死掉?

时间:2010-03-12 21:51:33

标签: java multithreading

在我的程序中,我在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!");

}

感谢帮助人员!

埃里克

9 个答案:

答案 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)

如果您选择ExecutorServiceThreadPoolExecutor框架,则有更好的选择。

  1. invokeAll

      

    执行给定的任务,在完成所有任务后返回持有其状态和结果的Futures列表。对于返回列表的每个元素,Future.isDone()都为true。请注意,已完成的任务可能正常终止或通过抛出异常终止。如果在此操作正在进行时修改了给定集合,则此方法的结果是不确定的。   输入参数:

  2. CountDownLatch:使用计数器初始化CountDownLatch作为线程数。使用countDown()await() API并等待计数器变为零。

  3. 进一步参考:

    How to use invokeAll() to let all thread pool do their task?

    How is CountDownLatch used in Java Multithreading?

答案 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
        }
    }
}