Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stopping thread Immediately

I want to stop a running thread immediately. Here is my code:

Class A :

public class A() {
    public void methodA() {
        For (int n=0;n<100;n++) {
        //Do something recursive
        }
        //Another for-loop here

        //A resursive method here

        //Another for-loop here

        finishingMethod();        
    }    
}

Class B:

public class B() {
    public void runEverything() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    A a = new A();
                    a.methodA();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
       Thread thread = new Thread(runnable);
       thread.start();
    }

My problem is that i need to be able to stop the thread in Class B even before the thread is finished. I've tried interrupt() method, but that doesn't stop my thread. I've also heard about using shared variable as a signal to stop my thread, but I think with long recursive and for-loop in my process, shared-variable will not be effective.

Any idea ? Thanks in advance.

like image 611
JrL Avatar asked Aug 11 '12 01:08

JrL


People also ask

How do you stop a thread immediately?

Modern ways to suspend/stop a thread are by using a boolean flag and Thread. interrupt() method. Using a boolean flag: We can define a boolean variable which is used for stopping/killing threads say 'exit'. Whenever we want to stop a thread, the 'exit' variable will be set to true.

Does a thread stop automatically?

A thread automatically terminates when it returns from its entry-point routine. A thread can also explicitly terminate itself or terminate any other thread in the process, using a mechanism called cancelation.

What should I use instead of thread stop?

interrupt() method is called from main() to terminate the thread. Invoking Thread. interrupt() sets an internal interrupt status flag.


2 Answers

Thread.interrupt will not stop your thread (unless it is in the sleep, in which case the InterruptedException will be thrown). Interrupting basically sends a message to the thread indicating it has been interrupted but it doesn't cause a thread to stop immediately.

When you have long looping operations, using a flag to check if the thread has been cancelled is a standard approach. Your methodA can be modified to add that flag, so something like:

// this is a new instance variable in `A`
private volatile boolean cancelled = false;

// this is part of your methodA
for (int n=0;n<100;n++) {
  if ( cancelled ) {
    return; // or handle this however you want
  }    
}

// each of your other loops should work the same way

Then a cancel method can be added to set that flag

public void cancel() {
  cancelled = true;   
}

Then if someone calls runEverything on B, B can then just call cancel on A (you will have to extract the A variable so B has a reference to it even after runEverything is called.

like image 70
Jeff Storey Avatar answered Oct 21 '22 05:10

Jeff Storey


I think you should persevere with using Thread.interrupt(). But what you need to do to make it work is to change the methodA code to do something like this:

public void methodA() throws InterruptedException {
    for (int n=0; n < 100; n++) {
        if (Thread.interrupted) {
             throw new InterruptedException();
        }
        //Do something recursive
    }
    // and so on.        
}

This is equivalent declaring and using your own "kill switch" variable, except that:

  • many synchronization APIs, and some I/O APIs pay attention to the interrupted state, and
  • a well-behaved 3rd-party library will pay attention to the interrupted state.

Now it is true that a lot of code out there mishandles InterruptedException; e.g. by squashing it. (The correct way to deal with an InterruptedException is to either to allow it to propagate, or call Thread.interrupt() to set the flag again.) However, the flip side is that that same code would not be aware of your kill switch. So you've got a problem either way.

like image 26
Stephen C Avatar answered Oct 21 '22 04:10

Stephen C