bayer
bayer

Reputation: 123

How do I wait for a set of threads to 'really' finish in java?

I have a group of threads in java that i want to run several times (each time with a different set of parameters). for the second run to start i want to wait for the first run to finish. this should be easily accomplished with Thread.join() before the second run, but since my threads run in an infinite loop i have to stop them with an interrupt, which also interrupts the blocking join:

I have a thread whose run() method looks basically like this:

try {  
    while(true) {  
        printSomeInfo();
        if (...) {
            Thread.currentThread().getThreadGroup().interrupt();
        }
    } 
} catch (InterruptedException e) {  
    Thread.currentThread().getThreadGroup().interrupt();  
} finally {  
    printStats();
}

and a main method invoking the run method of the thread:

System.out.println("New run:");
for (i ...) {    //first run
    myThread[i] = new MyThread(someInfoString1);
    myThread[i].start();
}
try {
    for (i...) {
        myThread[i].join();
    }
} catch (InterruptedException e) {
    e.printStackTrace();
}
System.out.println("New run:");
for (i ...) {    //second run
    myThread[i] = new MyThread(someInfoString2);
    myThread[i].start();
}
try {
    for (i...) {
        myThread[i].join();
    }
} catch (InterruptedException e) {
    e.printStackTrace();
}

My problem is that the second run starts printing out the info, without the first run being finished printing out with the printStats() method in the finally block. So the output looks like this:

New run:
Info 1
Info 1
...
Info 1
New run:
(here comes the stack trace)
Info 2
Info 2
Stats 1    <- this should happen before the second "New run:"
...
Info 2
Stats 2

how can i really wait for the first set of threads to finish? is there maybe a more selective way to interrupt the running threads?

Upvotes: 0

Views: 298

Answers (1)

Holger
Holger

Reputation: 298153

The problem lies in your repeated use of Thread.currentThread().getThreadGroup().interrupt() which interrupts all threads in your ThreadGroup, including the one which called join.

If you look at your loop, you are catching the InterruptedException, but not recovering correctly. Your loop is contained within the try…catch block and hence forcibly terminated by the exception. Since you want to call join on all threads, you must proceed with the loop, including the one join call that has been interrupted:

threads: for (i...) { // loop over all threads
    for(;;) { // recover join on InterruptedException
        try {
            myThread[i].join();
            continue threads; // after successful join
        } catch (InterruptedException e) {} // call join again
    }
}

Generally, interrupting an entire ThreadGroup, or dealing with the outdated concept of thread groups at all, is not a proper software design. You should rewrite your software to interrupt the inteded threads only. Or simply use the concurrency framework, esp. ExecutorService which already provides ways to submit groups of tasks and cancel or wait for all.

Upvotes: 2

Related Questions