Hello. I have such a problem - it is required to terminate the child threads if the thread that generated them is interrupted. The parent thread lives while the child is working using join() . Child threads use run() - while (!Thread.currentThread.isInterrupted) , that is, virtually infinite. The task is to interrupt the child threads when the parent is interrupted while not declaring the child threads as daemons.
3 answers
When I came across a similar task, I solved it like this:
In the child thread there was a boolean field running with standard get and set methods, the value of which was periodically checked. When the parent thread finished, it called the setRunning (false) method. At the next check, the child thread, seeing that running == false , went out of an infinite loop and finished the work.
Added sample code for a child thread.
public class A extends Thread{ private boolean running; public A(){ running = true; } public synchronized void setRunning(boolean r){ running = r; } public void run(){ while(!Thread.currentThread.isInteruped()) if(!running) break; } } - It does not work out for me, because the parent thread just hangs and waits until the end of the child threads. that is, everything is in it like this: childThread.start (); childThread.join () and need to be done so that by interrupting the thread, let's say the console terminates and generates - Vladimir
- That is, you start a child in the parent stream, tell the parent to wait until the child completes, but if the parent is tired of waiting and it completes, then you need to complete the children as well. So? - Sasha121
- Yes - Vladimir
- But the parental flow will not end by itself. It will complete something from the outside. Is this something from the outside can not get a link to the child thread of the parent stream to call the child setRunning (false)? - Sasha121
- ideally ctrl + c completes it in the console, it is simply injected. I now think whether the catch InterruptedException will catch in the parent and in the catch - child interactions - Vladimir
you need an implementation of the Observer pattern (option B in its pure form)
(option A is a bit constrained by the fact that the thread object is created inside the method, so Runnable is added as a parameter. you can do this with the help of generic, then your MainThread class will be more universal)
class MainThread extends Thread { private final Set < Thread > children = null; // variant A public Thread createChild ( final Runnable runnable ) { final Thread t = new Thread ( runnable ); // optional // t.start (); children.add ( t ); return t; } @Override public void interrupt () { removeAll (); super.interrupt (); } // variant B protected void add ( final Thread child ) { if ( ( null != child ) && !children.contains ( child ) ) { children.add ( child ); child.start (); } } protected void remove ( final Thread child ) { if ( children.contains ( child ) ) { children.remove ( child ); child.interrupt (); } } protected void removeAll () { final Iterator < Thread > iterator = children.iterator (); while ( iterator.hasNext () ) { iterator.next ().interrupt (); } } } class ChildThread extends Thread { public ChildThread ( final MainThread parent ) { parent.add ( this ); } public void interrupt() { if (isRunning) { isRunning = false; } } public void run() { if (!isRunning) { super.interrupt(); return; } // полезный код... если ChildThread и runImpl сделать абстрактными // то получится еще и красиво :) runImpl(); } } UP: according to the wishes of the public removed a rough interrupt: D
- I agree that this option is also possible and sometimes even more efficient, but the difference between my version is that the flow is not interrupted at the moment that is unpredictable for the child flow, but correctly ends the way the programmer wants. My method simply deduces a stream from an infinite loop, after which it can produce some result before completion. - Sasha121
- What I do not understand is that if a parent stream is roughly interrupted (say Ctrl + C from the console) it will have its interrupt () called? Is that so? In my opinion, join () will throw out InterruptedException and in catch it will be possible to interacte parent and children. Like so. Correct if not - Vladimir
- 2 @ Sasha121 doesn't remind you anything? :) why go into unnecessary details. trying to solve a problem that has already been solved. - jmu
- 2 @jmu - the same question - how will I interrupt if I just kill the process in the JVM? - Vladimir
- Killing the JVM process is also something that pulls the cord out of the socket. it is natural that nothing will be caused in the JVM. describe your task in more detail? it is not clear why you should stop JVM by such a rough method - jmu
Try looking towards CyclicBarrier
- What does CyclicBarrier do with it? My daughter flows are endless and never reach any logical barriers. I just want to stop the program (threads) correctly - Vladimir