Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regarding stopping of a thread

Tags:

java

I have developed a code that will start two threads upon executing

public class MyThread1 extends Thread //extend thread class 
{
    // public  synchronized void run()
     //synchronized (this)

     public   void run()
    {//synchronized(this)
        //{
         for(int i=0;i<20;++i) {
             try{
                 Thread.sleep(500);


          System.out.print(i +"\n"+ "..");
             }catch(Exception e)
             {e.printStackTrace();}
          //} 
        }

     }  

 public static void main(String... a) 
 {
     MyThread1 t = new MyThread1();

     Thread x = new Thread(t);

     Thread y = new Thread(t);
     x.start();
     y.start();

     }

Now it starts both the threads but what if I want to stop a particular thread, lets say I want to stop Thread Y then How I will do it please advise since stopping a thread means that it's run method is completed but I want to stop it forcefully how I will do this, please advise

like image 292
dghtr Avatar asked Feb 21 '23 16:02

dghtr


2 Answers

DISCLAIMER: this answer has a tutorial character.

BASIC APPROACH: we initially keep things simple and do not deal with the interruption during the Thread.sleep method. Essentially, you should have an externally settable variable over which the run method checks at every iteration of the loop; then you can set that variable to gracefully terminate the run() method. Please note how this idiom can be easily used for languages other than Java.

For example:

public class MyThreadedClass extends Thread {

  private volatile boolean completed = false;

  public void setCompleted() {
    this.completed = true;
  }

  public void run()
  {
    while (!completed) {
      // do anything you fashion
    }
  } 

  public static void main(String... args) 
  {
    MyThreadedClass x = new MyThreadedClass();
    MyThreadedClass y = new MyThreadedClass();

    x.start();
    y.start();

    x.setCompleted(); // will complete as soon as the latest iteration finishes

    ...
  }
}

COMMENTS: The volatile flag tells the compiler that completed may (and will) be changed outside the control of the run() function, i.e. another thread may change it. Otherwise the iterative check in the loop may be incorrectly optimized according to the sole synchronous behavior of the class.

In your particular run() case, we exploit the for loop, so our approach translates into the following:

public void run()
{
  try {
    for(int i=0;i<20 && !completed;++i) {        
      Thread.sleep(500);
      System.out.print(i +"\n"+ "..");
    } 
  } catch(Exception e) {
    e.printStackTrace();
  }
}

COMMENTS: as it is pretty obvious, you may have to wait up to 500 millis due to the sleep call. But if, in general, your code has to perform operations that alter the state of variables (in particular, if such variables are shared between multiple threads!), in this way you do not leave those variables in an incorrect state. In practice, you can properly handle a transaction since you control the termination. This obviously assumes that, at the end of each iteration of the loop, the variables state is consistent.

Let us now improve on the basic approach to handle interruption during Thread.sleep.

COMPLETE ANSWER: this answer involves, from the caller side, the use of the Thread.interrupt() method, which makes the approach strictly specific to Java.

public class MyThreadedClass extends Thread {

  public void run()
  {
    try {
      for(int i=0;i<20 && !this.isInterrupted();++i) {        
        Thread.sleep(500);
        System.out.print(i +"\n"+ "..");
        ...
        // some molassy slow code here, where you may sprinkle isInterrupted()
        // checks and consequent break statements 
      } 
    } catch(InterruptedException e) {
      // do whatever you need to clean things up
    } catch(Exception e) {
      // handle other exceptions as seen fit
    }
  }

  public static void main(String... args) 
  {
    MyThreadedClass x = new MyThreadedClass();

    x.start();

    // will complete 
    // a) as soon as one isInterrupted() check breaks the loop, or 
    // b) "immediately" during the blocking call to sleep()
    x.interrupt(); 

    ...
  }
}

COMMENTS: in this case, you already have half of your job done by Thread itself. If you only need to interrupt during the Thread.sleep call, then you do not need to do anything other than handling InterruptedException to clean up your state, if necessary. If instead you need to interrupt during the "slow" code, you must call this.isInterrupted() wherever you prefer (possibly in multiple places) and break the loop; the call inside the loop condition is common but not necessary.

More information can be found in the Java Concurrency Interrupts tutorial.

like image 52
13 revs Avatar answered Feb 23 '23 04:02

13 revs


You should interrupt() the thread. Blocking calls (like sleep()) will throw an InterruptedException when the thread is interrupted. If you want to stop as fast as possible while in a tight loop, regularly check is the current thread has been interrupted using the isInterrupted() method.

More information about this in the Java concurrency tutorial.

like image 24
JB Nizet Avatar answered Feb 23 '23 05:02

JB Nizet