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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:37:59  来源:igfitidea点击:

How do I pause main() until all other threads have died?

javamultithreading

提问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 == trueand then could fire if it was. Then it could do other things than just println

您可以将最后一行放在“监视”线程中。它会经常检查它是否是唯一正在运行的线程和一些完成状态== true,如果是,则可以触发。然后它可以做其他事情,而不仅仅是println

回答by Dan

You can use the join method. Refer to the documentation here

您可以使用 join 方法。请参阅此处的文档

回答by the-banana-king

You could share a CyclicBarrierobject among your RaceCars and your main thread, and have the RaceCarthreads invoke await()as soon as they are done with their task. Construct the barrier with the number of RaceCarthreads plus one (for the main thread). The main thread will proceed when all RaceCars have finished. See http://java.sun.com/javase/6/docs/api/java/util/concurrent/CyclicBarrier.html

您可以CyclicBarrierRaceCars 和主线程之间共享一个对象,并在RaceCar线程await()完成任务后立即调用它们。用RaceCar线程数加一(对于主线程)构造屏障。当所有RaceCars 完成后,主线程将继续进行。见http://java.sun.com/javase/6/docs/api/java/util/concurrent/CyclicBarrier.html

In detail, construct a CyclicBarrierin the main thread, and add a barrier.await()call in your RaceCarclass 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.

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

  1. invokeAll

    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:

  2. CountDownLatch: Initialize CountDownLatch with counter as number of threads. Use countDown()and await()APIs and wait for counter to become zero.

  1. 全部调用

    执行给定的任务,在全部完成后返回保存其状态和结果的 Future 列表。Future.isDone() 对于返回列表的每个元素都为真。请注意,已完成的任务可能已正常终止或通过抛出异常终止。如果在此操作进行时修改了给定的集合,则此方法的结果未定义。类型参数:

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

Further references:

进一步参考:

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

如何使用 invokeAll() 让所有线程池完成他们的任务?

How is CountDownLatch used in Java Multithreading?

Java 多线程中如何使用 CountDownLatch?