开发者

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

开发者 https://www.devze.com 2022-12-22 15:42 出处:网络
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 ha

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.

Is there a way to block the main() thread until all other threads have finished executing? Here is the relevant part of my code:

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(I开发者_JAVA百科nterruptedException 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


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.:

// 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!");


You could share a CyclicBarrier object among your RaceCars 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 RaceCars have finished. See 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.


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.


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


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.


You have better options if you go for ExecutorService or ThreadPoolExecutor framework.

  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.

Further references:

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

How is CountDownLatch used in Java Multithreading?


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


Simplest way

while (Thread.activeCount() > 1) {
}

I know it block main thread... but it works perfectly!


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
        }
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消