Thread start:
1. Description of the difference between start() and run()
start() : Its function is to start a new thread, and the new thread will execute the corresponding run() method. start() cannot be called repeatedly.
run() : run() can be called repeatedly just like ordinary member methods. If you call run() separately, run() will be executed in the current thread, and the new thread will not be started!
The following is a code to explain.
class MyThread extends Thread{ public void run(){ ... } };MyThread mythread = new MyThread(); mythread.start() starts a new thread and runs the run() method in the new thread.
Mythread.run() will run the run() method directly in the current thread, and will not start a new thread to run run().
2. Example of the difference between start() and run()
Below, demonstrate the difference between them with a simple example. The source code is as follows:
// Demo.java's source code class MyThread extends Thread{ public MyThread(String name) { super(name); } public void run(){ System.out.println(Thread.currentThread().getName()+" is running"); } };public class Demo { public static void main(String[] args) { Thread mythread=new MyThread("mythread"); System.out.println(Thread.currentThread().getName()+" call mythread.run()"); mythread.run(); System.out.println(Thread.currentThread().getName()+" call mythread.start()"); mythread.start(); } } Running results:
main call mythread.run()main is runningmain call mythread.start()mythread is running
Results description:
(1) Thread.currentThread().getName() is used to get the name of "current thread". The current thread refers to the thread that is scheduled to execute in the CPU.
(2) mythread.run() is called in "main thread main", and the run() method runs directly on "main thread main".
(3) mythread.start() will start "thread mythread". After "thread mythread" is started, the run() method will be called; at this time the run() method is run on "thread mythread".
Thread interrupts and terminations
1. Thread interrupt: interrupt()
The function of interrupt() is to interrupt the thread.
This thread is allowed to interrupt itself; when other threads call the interrupt() method of this thread, the permission will be checked through checkAccess(). This may throw a SecurityException exception.
If the thread is in a blocking state: calling wait(), wait(long) or wait(long, int) of the thread will make it into a waiting (blocking) state, or calling join(), join(long), join(long, int), sleep(long), sleep(long, int) of the thread will also make it into a blocking state. If the thread calls its interrupt() method when it is blocking, its "interrupt state" will be cleared and an InterruptedException will be received. For example, a thread enters a blocking state through wait(), and the thread is interrupted by interrupt(); calling interrupt() will immediately set the thread's interrupt flag to "true", but since the thread is in a blocking state, the "interrupt flag" will be immediately cleared to "false", and an InterruptedException will be generated.
If the thread is blocked in a Selector selector, then when it is interrupted by interrupt(); the thread's interrupt flag is set to true and it will be returned immediately from the selection operation.
If it does not belong to the situation mentioned above, then when the thread is interrupted through interrupt(), its interrupt flag will be set to "true".
Interrupting a "terminated thread" will not cause any action.
2. Thread termination
The stop() and suspend() methods in Thread are recommended not to be used due to their inherent insecurity!
Next, I will first discuss the termination method of threads in "blocking state" and "running state" respectively, and then summarize a general method.
1. Terminate the thread in the "blocking state"
Usually, we terminate a thread in a "blocking state" by "interrupting".
When the thread enters a blocking state due to being called sleep(), wait(), join() and other methods; if the interrupt() of the thread is called at this time, the interrupt mark of the thread is set to true. Since it is in a blocking state, the interrupt flag will be cleared and an InterruptedException exception is generated. Putting InterruptedException until it is appropriate can terminate the thread, in the form as follows:
@Overridepublic void run() { try { while (true) { // Execute the task... } } catch (InterruptedException ie) { // Due to an InterruptedException exception, exit the while(true) loop and the thread terminates! }} Note: When the task is continuously executed in while(true), when the thread is in a blocking state, the call to interrupt() of the thread generates an InterruptedException interrupt. The interrupted capture is outside while(true), thus exiting the while(true) loop!
Note: The capture of InterruptedException is usually placed outside the while(true) loop body, so that the while(true) loop exits when an exception is generated. Otherwise, if InterruptedException is within the while(true) loop body, additional addition and exit processing is required. The form is as follows:
@Overridepublic void run() { while (true) { try { // Execute task... } catch (InterruptedException ie) { // InterruptedException is in the while(true) loop body. // When the thread generates an InterruptedException exception, while(true) can continue to run! Need to manually exit break; } }} Note: The above InterruptedException exception is caught within whle(true). When an InterruptedException exception is generated, it is not handled by catch and is still in the while(true) loop body; to exit the while(true) loop body, an additional operation of exiting the while(true) need to be performed.
2. Terminate the thread in "running state"
Usually, we terminate a thread in a "running state" by "marking". Among them, it includes "interrupt flag" and "add additional flag".
(1) Terminate the thread through "interrupt flag".
The form is as follows:
@Overridepublic void run() { while (!isInterrupted()) { // Execute task... }} Description: isInterrupted() determines whether the interrupt flag of the thread is true. When the thread is in running state and we need to terminate it; the thread's interrupt() method can be called, and the thread's interrupt flag is marked true, that is, isInterrupted() will return true. At this point, the while loop will be exited.
Note: interrupt() does not terminate threads in "running state"! It sets the thread's interrupt flag to true.
(2) Pass "Add additional marks".
The form is as follows:
private volatile boolean flag= true;protected void stopTask() { flag = false;}@Overridepublic void run() { while (flag) { // Execute task... }} Description: There is a flag tag in the thread, and its default value is true; and we provide stopTask() to set the flag tag. When we need to terminate the thread, calling the stopTask() method of the thread can cause the thread to exit the while loop.
Note: The flag is defined as the volatile type to ensure the visibility of the flag. That is, after other threads modify the flag through stopTask(), this thread can see the modified flag value.
Comprehensive the termination methods of threads in "blocking state" and "running state", the more common termination threads are as follows:
@Overridepublic void run() { try { // 1. isInterrupted() guarantees that the thread will be terminated as long as the interrupt is marked true. while (!isInterrupted()) { // Execute task... } } catch (InterruptedException ie) { // 2. InterruptedException exception guarantees that when an InterruptedException exception occurs, the thread is terminated. }} 3. Example of terminating thread
interrupt() is often used to terminate a "blocking state" thread. Refer to the following example:
// Demo1.java's source code class MyThread extends Thread { public MyThread(String name) { super(name); } @Override public void run() { try { int i=0; while (!isInterrupted()) { Thread.sleep(100); // Sleep 100ms i++; System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i); } } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException."); } }}public class Demo1 { public static void main(String[] args) { try { Thread t1 = new MyThread("t1"); // Create a new "thread t1" System.out.println(t1.getName() +" ("+t1.getState()+") is new."); t1.start(); // Start "thread t1" System.out.println(t1.getName() +" ("+t1.getState()+") is started."); // The main thread sleeps for 300ms, and then the main thread sends an "interrupt" instruction to t1. Thread.sleep(300); t1.interrupt(); System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted."); // The main thread sleeps for 300ms, and then checks the status of t1. Thread.sleep(300); System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now."); } catch (InterruptedException e) { e.printStackTrace(); } } } Running results:
t1 (NEW) is new.t1 (RUNNABLE) is started.t1 (RUNNABLE) loop 1t1 (RUNNABLE) loop 2t1 (TIMED_WAITING) is interrupted.t1 (RUNNABLE) catch InterruptedException.t1 (TERMINATED) is interrupted now.
Results description:
(1) The main thread main creates thread t1 through new MyThread("t1"), and then starts thread t1 through t1.start().
(2) After t1 is started, its interrupt flag will be checked continuously. If the interrupt flag is "false", it will sleep for 100ms.
(3) After t1 sleeps, it will switch to the main thread main; when the main thread runs again, t1.interrupt() will be executed to interrupt thread t1. After t1 receives the interrupt instruction, the interrupt flag of t1 will be set to "false" and an InterruptedException will be thrown. In the run() method of t1, it is an exception caught outside the loop body while; therefore the loop is terminated.
We made a small modification to the above result and moved the code block that caught the InterruptedException exception in the run() method to the while loop body.
// Demo2.java's source code class MyThread extends Thread { public MyThread(String name) { super(name); } @Override public void run() { int i=0; while (!isInterrupted()) { try { Thread.sleep(100); // Sleep for 100ms } catch (InterruptedException ie) { System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException."); } i++; System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i); } }}public class Demo2 { public static void main(String[] args) { try { Thread t1 = new MyThread("t1"); // Create a new "thread t1" System.out.println(t1.getName() +" ("+t1.getState()+") is new."); t1.start(); // Start "thread t1" System.out.println(t1.getName() +" ("+t1.getState()+") is started."); // The main thread sleeps for 300ms, and then the main thread sends an "interrupt" instruction to t1. Thread.sleep(300); t1.interrupt(); System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted."); // The main thread sleeps for 300ms, and then checks the status of t1. Thread.sleep(300); System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now."); } catch (InterruptedException e) { e.printStackTrace(); } } } Running results:
t1 (NEW) is new.t1 (RUNNABLE) is started.t1 (RUNNABLE) loop 1t1 (RUNNABLE) loop 2t1 (TIMED_WAITING) is interrupted.t1 (RUNNABLE) catch InterruptedException.t1 (RUNNABLE) loop 3t1 (RUNNABLE) loop 4t1 (RUNNABLE) loop 5t1 (TIMED_WAITING) is interrupted now.t1 (RUNNABLE) loop 6t1 (RUNNABLE) loop 7t1 (RUNNABLE) loop 8t1 (RUNNABLE) loop 9...
Results description:
The program has entered a dead loop!
Why is this happening? This is because t1 is interrupted by interrupt() when it is "waiting for (blocking) state". At this time, the interrupt flag is cleared [that is Interrupted() will return false], and an InterruptedException exception is thrown [this exception is caught in the while loop body]. Therefore, t1 will naturally enter a vicious cycle.
To solve this problem, we need to extra processing to exit the while loop when catching the exception. For example, adding break or return to MyThread catch(InterruptedException) can solve the problem.
Here is an example of a thread that terminates a "status state" by "adding additional tags":
// Demo3.java's source code class MyThread extends Thread { private volatile boolean flag= true; public void stopTask() { flag = false; } public MyThread(String name) { super(name); } @Override public void run() { synchronized(this) { try { int i=0; while (flag) { Thread.sleep(100); // Sleep 100ms i++; System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i); } } catch (InterruptedException ie) { System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException."); } } }} public class Demo3 { public static void main(String[] args) { try { MyThread t1 = new MyThread("t1"); // Create a new "thread t1" System.out.println(t1.getName()) +" ("+t1.getState()+") is new."); t1.start(); // Start "thread t1" System.out.println(t1.getName() +" ("+t1.getState()+") is started."); // The main thread sleeps for 300ms, and then the main thread sends an "interrupt" instruction to t1. Thread.sleep(300); t1.stopTask(); System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted."); // The main thread sleeps for 300ms, and then checks the status of t1. Thread.sleep(300); System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now."); } catch (InterruptedException e) { e.printStackTrace(); } } } Running results:
t1 (NEW) is new.t1 (RUNNABLE) is started.t1 (RUNNABLE) loop 1t1 (RUNNABLE) loop 2t1 (TIMED_WAITING) is interrupted.t1 (RUNNABLE) loop 3t1 (TERMINATED) is interrupted now.