Summary of methods for stopping thread execution in Java

Source: Internet
Author: User
Tags deprecated documentation sleep thread stop throwable visibility volatile

method of stopping thread execution in Java

The theory of pausing or stopping a thread

In Java programming, there are several ways to pause or stop a currently running thread. Using Thread.Sleep () is the most correct way to put a thread into sleep sleeping state. Some may ask, why not use waiting Wait () or notify Notify ()? You know, it's not a good way to use wait or notice.
A thread can be blocked by waiting for a wait () implementation, which is the way the condition waits, and when the condition is met, it is turned from blocking to waiting. Although you can put a time-out setting waiting for wait () conditions, waiting for wait () is not designed to be the case, waiting for Wait () is designed to be used for communication between Java threads.
Instead, you can allow a thread to sleep at a specified time from the current start. Be careful not to replace waiting for wait () or notify Notify (), or vice versa, by sleeping sleep ().
Example of Java thread communication: http://javarevisited.blogspot.sg/2013/12/inter-thread-communication-in-java-wait-notify-example.html
Waiting for Wait () or notification that notify () should not be used to suspend the thread, there is another reason for waiting () or notifying notify () that a lock is required. They can only be invoked from a synchronized method or a synchronized code block, and the overhead of acquiring a lock and releasing a lock is relatively large. Furthermore, it is not necessary to introduce a lock mechanism if the thread is paused.
Sleep () is a bit different from wait (), and sleep () turns the current thread into a waiting state, it does not release any locks it holds, and wait () causes the thread to go into a blocking state, releasing the lock it holds.
In short, Java multithreaded programming is not simple, even simple tasks, such as creating a thread, stopping a thread, or pausing a thread, require careful mastering of the Java API.

second, suspend or stop the actual combat of the thread

In the following example, to suspend a thread, you can use either the Thread.Sleep () or the Timeunit.sleep () method. In the example, there are two threads, the main thread is started by the JVM, and it executes the main () method. The second thread is called T1, which is created by the main thread to loop through the game. The runnable task we pass is an infinite loop that will run until we stop it. Notice that I used the volatile keyword.
The main thread starts the T1 thread first, and then stops the thread using the Stop () method.
In this example, there are two ways to stop a thread from running, using the Thread.Sleep () method, or using the Timeunit.sleep () method. The Timeunit class can specify either a second or a timeunit.seconds, or a millisecond that is timeunit.milliseconds. In general, using the Timeunit sleep () method makes the code easier to read.

Click (here) to collapse or open

Import static java.lang.Thread.currentThread;
Import Java.util.concurrent.TimeUnit;
public class threadpausedemo{
public static void Main (String args[]) throws Interruptedexception {
Game Game = new Game ();
thread T1 = new Thread (game, "T1");
T1.start ();
Stop Game Thread Now
System.out.println (CurrentThread (). GetName () + "is stopping game thread");
Game.stop ();
To view the state of the game thread stop
TimeUnit.MILLISECONDS.sleep (200);
System.out.println (CurrentThread (). GetName () + "is finished now");
}
}


Click (here) to collapse or open

class game implements runnable{    private volatile boolean 
isstopped = false;     public void run () {        while (! isstopped) {            system.out.println ("Game
 thread is running ... ");             system.out.println ("Game thread
 is now going to pause ");             try{     
           thread.sleep (200);             } catch (InterruptedException  e) {                
E.printstacktrace ();             }          
   system.out.println ("game thread is now resumed ...");         }         
System.out.println ("game thread is stopped ...");    &NBSP}     public void stop () {     
   isStopped = true;    &NBSP}}


The program output is as follows:
Game Thread is running ...
Main is stopping game thread
Game thread is now going to pause
Game thread is now resumed ...
Game thread is stopped ...
Main is finished now

Note:
Volatile keyword: When a shared variable is decorated with volatile, it guarantees that the modified value is immediately updated to main memory, and that it will read the new value in main when there is another thread that needs to read it. The volatile keyword guarantees visibility. Ordinary shared variables do not guarantee visibility, because when the normal shared variable is modified and when it is written to main memory is indeterminate, when other threads go to read, the memory may still be the old value, so the visibility cannot be guaranteed.
Visibility can also be ensured through synchronized and lock, and synchronized and lock ensure that only one thread acquires the lock at the same time and then executes the synchronization code, and the modifications to the variable are flushed to main memory before the lock is released. Therefore, visibility can be guaranteed.
A shared variable (a member variable of a class, a static member variable of a class) is volatile decorated, and then it has two layers of semantics:
1. The visibility of the variable is guaranteed by the different threads, that is, a thread modifies the value of a variable, which is immediately visible to other threads.
2. The instruction reordering is prohibited.
The volatile keyword prohibits order reordering with two layers of meaning:
1. When a program executes a read or write operation to a volatile variable, the changes in the previous operation must have been made, and the result is visible to the subsequent operation, and the operation behind it must not have been done.
2. When the instruction is optimized, the statements that are accessed by the volatile variable cannot be executed behind it, nor can the statements following the volatile variable be executed before it.
Volatile is generally not a substitute for sychronized, because volatile does not guarantee the atomic nature of the operation, even if only the i++, is actually composed of several atomic operations: Read I; Inc; Write I, if multiple threads execute at the same time I++,volatile can only guarantee that they operate the same piece of memory, but still can write dirty data.

three, Sleep () method summary

The Thread.Sleep () method allows the thread to pause or stop, and there are some details to note:
1. The Thread.Sleep () method is a static method that always lets the current thread go to sleep.
2. You can call the interrupt () method to wake up the current sleep thread.
3. The sleep () method does not guarantee that the thread will be able to turn on the specified millisecond accurately, and its precision depends on the system's timer.
4. It does not release the locks it obtains.




How to stop Java threads

How to stop a Java thread has been a problem for us to develop multithreaded programming. The problem was eventually answered in Java5 's java.util.concurrent: Use Interrupt () to let the thread stop in the Run method.
Brief introduction

In Java multithreaded programming, the Java.lang.Thread type contains some of the column's method start (), Stop (), Stop (Throwable) and suspend (), Destroy () and resume (). With these methods, we can easily manipulate threads, but only the start () method is preserved in these methods.

In a Sun company article "Why are Thread.stop, thread.suspend and Thread.Resume deprecated?" Explains the reasons for abandoning these methods in detail. So how exactly should we stop the thread?


Suggested methods of use

In the Why are Thread.stop, thread.suspend and Thread.Resume deprecated? , we recommend that you stop the thread by using the following methods:

    private volatile Thread blinker;     public void stop ()  {        
blinker = null;    &NBSP}     public void run ()  {    
    thread thisthread = thread.currentthread ();         while  (blinker == thisthread)  {             try {     
           thisthread.sleep (interval);             } catch  ( interruptedexception e) {            }  
           repaint ();          }     } 


For a reason to use the volatile keyword, see http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#36930.
When a thread is in a non-running (run) state

When a thread is in the following state, it is not running:

When the sleep method is invoked.

When the wait method is invoked.

When blocked by I/O, it may be a file or network, and so on.

When the thread is in the above state, using the method described earlier is not available. At this time, we can use interrupt () to break the blocking situation, such as:

public void Stop () {
Thread tmpblinker = blinker;
Blinker = null;
if (Tmpblinker!= null) {
tmpblinker.interrupt ();
}
}


When interrupt () is called, the interruptedexception is thrown, so you can catch the exception in the Run method and let the thread safely exit:

try {
....
Wait ();
} catch (Interruptedexception IEX) {
throw new RuntimeException ("interrupted", IEX);


Blocked I/O

When a thread is blocked by I/O, the call to interrupt () is dependent on the actual running platform. Interruptedioexception exceptions will be thrown on Solaris and Linux platforms, but there is no such exception on Windows. Therefore, we can not deal with this problem depends on the implementation of the platform. Such as:

Package com.cnblogs.gpcuster import java.net.*;
import java.io.*; public abstract class interruptiblereader extends thread {   
 private object lock = new object ( );
    private InputStream is;
    private boolean done;
    private int buflen;
    protected void processdata (Byte[] b, int n)  { }     class readerclass extends thread {         public void run ( )  {        
    byte[] b = new byte[buflen];             while  (!done)  {                  try {             
       int n = is.read (B, 0, buflen);                   
  processdata (B, n);                 } catch   (Ioexception ioe)  {            
        done = true;                 }              }              synchronized (lock)  {                &nbSp;lock.notify ( );             }         &NBSP}     }     public interruptiblereader (InputStream
 is)  {        this (is, 512);          public interruptiblereader (Inputstream is, int len)  { 
       this.is = is;
        buflen = len;    &NBSP}     public void run ( )  {   
     readerclass rc = new readerclass ( );         synchronized (lock)  {      
      rc.start ( );             while  (!done)  {                 try {        
            lock.wait ( );                 } catch   (Interruptedexception ie)  {           
         done = true;                   
  rc.interrupt ( );                      try {                     &nbsP;   is.close ( );                      } catch  (Ioexception ioe)  {}                  }              }         }     }



In addition, we can also use the Interruptiblechannel interface. A class that implements the Interruptiblechannel interface can throw closedbyinterruptexception when it is blocked. For example,

Package com.cnblogs.gpcuster import java.io.bufferedreader;
import java.io.filedescriptor;
import java.io.fileinputstream;
import java.io.inputstream;
import java.io.inputstreamreader;
import java.nio.channels.channels; public class interruptinput {        static  Bufferedreader in = new bufferedreader (             new inputstreamreader (             channels.newinputstream (           
  (New fileinputstream (filedescriptor.in)). Getchannel ()));          public static void main (string args[])  {        try {             system.oUt.println ("enter lines of input  (user ctrl+z enter to terminate):");             system.out.println ("(Input thread
 will be interrupted in 10 sec.) ");             // interrupt input in  10 sec              (New timeout ()).
Start ();
            String line = null;             while  (line =  In.readline ())  != null)  {           
     system.out.println ("Read line:" "+line+");             }         } catch  (Exception ex)  {     
       system.out.println (Ex.tostring ());  // printstacktrace ();        &NBSP}     }           public static class timeout extends thread {    
    int sleepTime = 10000;         Thread threadToInterrupt = null;              public timeout ()  {             // interrupt thread that creates
 this timeout.             threadToInterrupt = 
Thread.CurrentThread ();     &nbSp;       setdaemon (TRUE);         }                   public void run ()  {             try {                 sleep (10000);  // wait 10 sec     
        } catch (Interruptedexception ex)  {/*ignore*/}
            threadtointerrupt.interrupt ();         }    &nbsp}}


It is also important to note that when the thread is in the state of the write file, the call to interrupt () does not interrupt the thread.



How to stop a thread in Java correctly

Why can't I use the Thread.stop () method?

can be learned from Sun's official documentation that calling the Thread.stop () method is unsafe because the following two things happen when the Thread.stop () method is invoked:

1. Instantly throws Threaddeath exception, Any point within the run () method of a thread can throw Threaddeath Error, including in a catch or finally statement.
2. Releases all locks held by the thread


When a thread throws a Threaddeath exception, it causes the thread's run () method to suddenly return to stop the thread. The Threaddetath exception can be thrown at any one of the execution points of the thread run () method. However, does the thread's Stop () method return immediately once the calling thread's run () method is invoked?

Public static void main (String[] args)  {             try {                 thread t = new thread ()  {                     public synchronized void  run ()  {                         try {                              long start=system.currenttimemillis ();                             for   (int i =  0; i < 100000; i++)                                   system.out.println ("runing ...")  + i);                             system.out.println ( System.currenttimemillis ()-start)/1000);                         } catch  (Throwable ex)  {                             system.out.println ("Caught in run:  " + ex);    &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSp;            ex.printstacktrace ();                          }                     }                 };                t.start ();                 // give t  time to get going...                 thread.sleep (;   )              t.stop (); // expect compiler warning             } catch  (throwable t)  {                 system.out.println ("caught in main: "  +  t);                
T.printstacktrace ();            }           }   Public static void main (String[] args)  {           try {                thread t = new thread ()  {                    public  synchronized void run ()  {                        try {                            long  Start=system.currenttimemillis ();                            for  (int i  = 0; i < 100000; i++)                                  system.out.println ("runing ...")  + i);                            system.out.println ((System.currentTimeMillis ()-start)/1000);                       } catch  (Throwable ex)  {                            system.out.println ("caught in run: "  + ex);                             ex.printstacktrace ();                        }                    }                };                t.start ();                // Give t time to get going...                thread.sleep (;  )      
       t.stop (); // expect compiler warning           } catch  (throwable t)  {                system.out.println ("Caught in main :  " + t);               
T.printstacktrace ();           }          }


Let's say we're like the last worker thread, it's working in numbers, from 1 to 1000000, and our goal is to stop the thread when it's counting. If we call the Thread.stop () method in the way above, we can achieve our goal in principle, according to the Sun official documentation, plus in the above program, the main thread only sleeps 100ms, while the working thread takes about 1 to 1000000 of the time is probably 4-5s, Then the worker thread should only count from 1 to a value (less than 1000000), and then the thread stops.

But according to the results of the operation, this is not the case.

Results:

。。。

Runing.. 99998
Runing.. 99999

5

。。。

Runing.. 99998
Runing.. 99999
4

The results of each run indicate that the worker thread does not stop, but that it succeeds every time, and then terminates normally, rather than terminated by the stop () method. What is this for? According to Sun's documentation, in principle, as soon as a call to the Thread.stop () method, the thread will immediately stop, and throw Threaddeath error, look at the source code of thread to find that the original Thread.stop0 () method is synchronized, and the Run () method of our worker threads is also synchronized, this causes the main thread and worker threads to contend with the same lock (the worker thread object itself), because the worker thread gets the lock first after it starts, so at any rate, when the main thread calls T.stop (), it must wait until the worker thread's run ( After the execution of the method is completed, the result is the strange phenomenon.

Remove the Run () method of the above worker thread and execute it, as described in the 1th above.

Possible results:

Runing.. 4149
Runing.. 4150
Runing.. 4151
Runing.. 4152runing.. 4152Caught in Run:java.lang.ThreadDeath

Or

Runing.. 5245
Runing.. 5246
Runing.. 5247
Runing.. 5248runing.. 5248Caught in Run:java.lang.ThreadDeath


The next step is to see if the stopped thread will release the lock it holds when calling Thread.stop (), and look at the following code:


Public static void main (String[] args)  {             final object lock = new object ();             try {          
      thread t0 = new thread ()  {                    public  Void run ()  {                         try {                              synchronized  (lock)  {                  &nBsp;              system.out.println (" Thread-> " + getname ()                                           +  " acquire lock.");                                  sleep (3000);// sleep  for 3s                                 system.out.println (" Thread-> " + getname ()                                           +  " release lock.");                              }                         } catch  ( THROWABLE&NBSP;EX)  {                             system.out.println ("Caught  in run:  " + ex);                             ex.printstacktrace () ;                        }                     }                 };             
      thread t1 = new thread ()  {                    public  Void run ()  {                         synchronized  (lock)  {                              system.out.println ("thread->"  + getname ()                                       +  " acquire lock.");                          }                     }                 };                    t0.start ();                 // Give t time to get going...                 thread.sleep (;   )           &nbSp;  //t0.stop ();                 t1.start ();            } catch  ( throwable t)  {                 system.out.println ("caught in main: "  + t);                 t.printstacktrace ();             }           }             Public static void main (String[] args)  {        final object lock = new object ();        try {           thread t0 =  new Thread ()  {               public  void run ()  {                    try {            
           synchronized  (Lock)  {                            system.out.println ("thread->"  + getname ()                                      +  " acquire lock.");                              sleep (3000);// sleep for 3s                             system.out.println ("thread->"  + getname ()                                      +  " release lock.");                         }                    } catch  (Throwable ex)  {                        system.out.println (" caught in run:  " +&nbsP;EX);                        ex.printstacktrace ();                    }          
     }           };           thread t1 = new thread ()  {                public void run ()  {                    synchronized  (lock)  {                        system.out.println ("thread->"  +  GetName ()                                 +  " acquire lock.");                    }                }            };           t0.start ();            // give t time to get  going...           thread.sleep (;  )          //t0.stop ();          
 t1.start ();       } catch  (throwable t)  {         &nBsp; system.out.println ("caught in main: "  + t);            t.printstacktrace ();       }  }



When a call to the T0.stop () method is not made, it can be found that the order in which two threads are contending for locks is fixed.

Output:

Thread->thread-0 acquire lock.
Thread->thread-0 release lock.
Thread->thread-1 acquire lock.


But after invoking the T0.stop () method, (removing the comment//t0.stop () above), you can find that the t0 thread throws Threaddeath error and the T0 thread frees its lock.


Output:

Thread->thread-0 acquire lock.
Thread->thread-1 acquire lock.
Caught in Run:java.lang.ThreadDeath
Java.lang.ThreadDeath
At Java.lang.Thread.stop (thread.java:715)
At Com.yezi.test.timeout.ThreadStopTest.main (threadstoptest.java:40)

From the above program verification results, Thread.stop () is indeed unsafe. Its insecurity is primarily focused on the 2nd: releasing all the locks held by the thread. In general, any block of code that is locked is intended to protect the consistency of the data, and if the call to Thread.stop () results in a sudden release of all locks held by the thread, the protected data is likely to render an inconsistency, while other threads are using the corrupted data May cause some very strange application errors.


How to stop a thread correctly

This article (How to stop thread) gives a good answer to the proper stopping of threads, summed up 3 points below (when stopping threads):

1. Use the violate Boolean variable to identify whether the thread is stopped
2. When stopping a thread, you need to invoke the interrupt () method of the stop thread, because the thread may be waiting () or sleep () to increase the immediacy of the stop thread
3. For blocking IO processing, try to use Interruptiblechannel instead of blocking IO


The core is as follows:

If you are writing your own small thread then you should
 follow the following example code.
private volatile thread mythread;
Public void stopmythread ()  {    Thread tmpThread = myThread;
    myThread = null;     if  (tmpthread != null)  {       
 tmpthread.interrupt (); &NBSP;&NBSP;&NBSP;&NBSP} public void run ()  {    if  (mythread ==  null)  {       return; // stopped before 
Started. &NBSP;&NBSP;&NBSP;&NBSP}     try {        //  all the run ()  method ' S code goes here             &nbs.P;     // do some work          Thread.yield ();  // let another thread have some time perhaps to
 stop this one.         if  (Thread.CurrentThread (). isinterrupted ())  {            throw new interruptedexception ("Stopped
 by ifinterruptedstop () ");         }         // do  some more work                catch  (throwable t)  {       // log/handle  All errors here    &nbsp}}


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.