简体   繁体   中英

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 ?

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 (ie, 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.

Look, you can keep on a shared global array all the Thread objects, then at the end of each task you can perform a call to a "cleanup" function that just takes all these objects and performs a call to "interrupt" on them. That would cause the first thread to finish to finish the execution of the rest.

public class MyMain
{
   public static Thread workers[NUM_WORK];
   public static void main(..)
   {
      MyMain.workers[0] = new Thread(new MyTask0());
      .
      .
      .
      MyMain.workers[n] = new Thread(new MyTaskN());
      //Then start them all..
      // And wait for them unless you want them to die before execution ;)
   }
}

Then on your other workers

import MyMain;
public class MyTaskI implements Runnable
{
   public void run()
   {
      //Do all the work
      for(Thread t : MyMain.workers)
      {
         // If it is not this thread
         t.interrupt();
      }
   }
}

Sorry if I made any syntax errors. It's been a while since I did Java, the idea is that you get the point ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM