Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Communication between java threads: stopping all threads when one finishes its task

I have n threads running in parallel and each of them does some custom logic. However, my requirement is that when any of the threads finishes it execution, all other threads should stop execution and return.

What is the best way to implement this ? I thought of doing this by having a shared boolean variable. When any of the threads finishes it execution, it will set the boolean. All all the threads periodically read this variable and exit if when it is set.

Also, my custom logic is an infinite loop and as soon as i know some other thread has finished execution I want to stop execution after the current iteration.

What is the proper way of doing this ?

like image 368
shadowfax Avatar asked Jun 18 '13 10:06

shadowfax


People also ask

What happens to a thread when it finishes Java?

A thread is automatically destroyed when the run() method has completed.

What happens to thread pool after it finishes its task?

Once a thread in the thread pool completes its task, it's returned to a queue of waiting threads. From this moment it can be reused. This reuse enables applications to avoid the cost of creating a new thread for each task.

How do Java threads communicate with each other?

Inter-thread communication in Java is a mechanism in which a thread is paused running in its critical section and another thread is allowed to enter (or lock) in the same critical section to be executed. Note: Inter-thread communication is also known as Cooperation in Java.

Which stops the execution of a thread in Java?

Whenever we want to stop a thread from running state by calling stop() method of Thread class in Java. This method stops the execution of a running thread and removes it from the waiting threads pool and garbage collected.


2 Answers

Use an ExecutorService and its .invokeAny() method (note: there is also a version with a timeout).

From the Javadoc:

Executes the given tasks, returning the result of one that has completed successfully (i.e., without throwing an exception), if any do.

One you have your result, .shutdown() the executor.

See the Executors class to obtain an executor which fits your needs.

Another solution is the ExecutorCompletionService class; in this Case you'd .take() instead of .invokeAny(), and would have to submit each task one by one. And you'd also have to keep a reference to your ExecutorService since you need one as an argument, and need to shut it down as well.

(note: if you don't return a result, make Callable<Void> instances)

like image 184
fge Avatar answered Sep 18 '22 20:09

fge


I would prefer to use a common semaphore to control the execution, and have a frequent check in the threads.

public class MyTask implements Runnable {
    private static volatile boolean isDone = false
    @Override
    public void run() {
        while(true) {
            if (isDone) {
                break;
            }

            // do some calculation, no wait() s

            if (...has result...) {
                isDone = true;
                break;
            }
        }
    }
}

Thread t1 = new Thread(new MyTask());
Thread t2 = new Thread(new MyTask());
Thread t3 = new Thread(new MyTask());
t1.start();
t2.start();
t3.start();

The only thing you must be aware of is the static volatile boolean variable. Static because the same flag must be accessed by all threads, volatile to prevent the JVM to cache its data. If you don't mark it as volatile, the compiler may produce such a bytecode that it would optimize the read from a field such a way that it reads the field only once, and uses the saved value for every loop execution.

If your tasks are different and you implement different loops, you can use any external public static volatile boolean field to hold the flag.

This solution does not depend on the wait state of the thread. You can check isDone multiple places in your loop (even before every block of code). If you guarantee that your code will reach an exit check, there is no need to interrupt the threads anyway.

like image 25
gaborsch Avatar answered Sep 17 '22 20:09

gaborsch