Given two Java threads, stop one thread when one of them ends

I am looking for a clean design / solution for this problem: I have two threads that can work as long as the user wants, but end up when the user issues a stop command. However, if one of the threads ends abruptly (for example, due to an exception at runtime), I want to stop the other thread.

Now both threads execute Runnable (so when I say stop the thread, I mean that I call the stop () method on the Runnable instance), I think that you should avoid using threads (Thread class) and use the CompletionService interface. and then send both Runnables to an instance of this service.

With this, I would use the CompletionService take() method, when this method returns, I would stop both Runnables, since I know that at least one of them has already been completed. Now it works, but if possible, I would like to know a simpler / better solution for my case.

Also, what is a good solution when we have n threads, and as soon as one of them ends to stop all the others?

Thanks in advance.

+3
source share
3 answers

There is no Runnable.stop() method, so it is an obvious non-starter.

Do not use Thread.stop() ! This is basically unsafe in the vast majority of cases.

Here are a few approaches that should work if implemented correctly.

  • You can have both threads regularly check the common flag variable (for example, call it stopNow ) and arrange for both threads to set it when they are done. (The flag variable must be mutable ... or correctly synchronized.)

  • You can have both threads calling Thread.isInterrupted() regularly to see if it was interrupted. Then each thread should call Thread.interrupt() on the other when it ends.


I know that Runnable does not have this method, but my Runnable implementation, which I pass to the threads, has it, and by calling it, the runner will end the run () method (something like Corsika code, below this answer).

From what I can tell, Corsica's code assumes that there is a stop() method that will do the right thing when called. The real question is: how did you implement it? Or how are you going to implement it?

  • If you already have an implementation that works, then you have a solution to the problem.

  • Otherwise, my answer gives two possible approaches to the implementation of the "stop now" function.

I appreciate your suggestions, but I have doubts about how to "regularly check / call" translate into code?

This completely depends on the task that the Runnable.run() method performs. This is usually due to the addition of a check / call for certain cycles, so that the test passes often enough ... but not too often. You also want to check only when it would be safe to stop the calculation, and this is another thing that you must decide for yourself.

+6
source

The following should help you give you some ideas on how you can apply it to your problem. Hope this helps ...

  import java.util.*; public class x { public static void main(String[] args) { ThreadManager<Thread> t = new ThreadManager<Thread>(); Thread a = new MyThread(t); Thread b = new MyThread(t); Thread c = new MyThread(t); t.add(a); t.add(b); t.add(c); a.start(); b.start(); c.start(); } } class ThreadManager<T> extends ArrayList<T> { public void stopThreads() { for (T t : this) { Thread thread = (Thread) t; if (thread.isAlive()) { try { thread.interrupt(); } catch (Exception e) {/*ignore on purpose*/} } } } } class MyThread extends Thread { static boolean signalled = false; private ThreadManager m; public MyThread(ThreadManager tm) { m = tm; } public void run() { try { // periodically check ... if (this.interrupted()) throw new InterruptedException(); // do stuff } catch (Exception e) { synchronized(getClass()) { if (!signalled) { signalled = true; m.stopThreads(); } } } } } 

If you use the stop or interrupt flag, you need to check periodically to stop the thread.

+3
source

You can give them access to eachother or a callback to what had access to both so that it can interrupt the other. Consider:

 MyRunner aRunner = new MyRunner(this); MyRunner bRunner = new MyRunner(this); Thread a = new Thread(aRunner); Thread b = new Thread(brunner); // catch appropriate exceptions, error handling... probably should verify // 'winner' actually is a or b public void stopOtherThread(MyRunner winner) { if(winner == aRunner ) bRunner .stop(); // assumes you have stop on class MyRunner else aRunner.stop(); } // later a.start(); b.start(); // in your run method public void run() { // la de da de da // awesome code while(true) fork(); // other code here myRunnerMaster.stopOtherThread(this); } 
+1
source

All Articles