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 ?
A thread is automatically destroyed when the run() method has completed.
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.
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.
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.
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)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With