Interrupt in java thread

Reference case: https://www.cnblogs.com/myseries/p/10918819.html

1. Thread interrupt

Interrupt ing a thread means stopping everything it is doing before it completes its task, effectively aborting its current operation. Whether the thread dies, waits for a new task, or continues to run to the next step depends on the program. Although it may seem simple at first, you must take some early warning to achieve the desired results. You'd better keep the following caveats in mind.

First, forget thread Stop method. Although it does stop a running thread, this method is unsafe and not advocated, which means that it will no longer exist in future JAVA versions.

1.1. How to safely end a running thread

Methods related to Thread class

  java.lang.Thread class contains some common methods, such as: start(), stop(), stop (throwable), suspend(), destroy(), resume(). Through these methods, we can easily operate the thread, but among these methods, only the start () method is retained.

In the JDK help document and an article "Why are thread.stop, thread.suspend and thread. Resume deferred?" The reasons for abandoning these methods are explained in.

To put it simply, although using the stop method can forcibly terminate the running or suspended thread, using the stop method is very dangerous. It may produce unpredictable results, just like suddenly turning off the computer power instead of shutting down according to the normal program. Therefore, it is not recommended to use the stop method to terminate the thread.

In other words, illegally closing some tasks that have not been terminated or running programs may cause waste and impact on resources.

1. 2 how to properly stop threads

  • 1. There is usually a loop structure in a task. As long as you control the loop with a mark, you can end the task.
  • 2. If the thread is frozen and cannot read the tag, you can use the interrupt() method to forcibly restore the thread from the frozen state to the running state to make the thread qualified for CPU execution.

1.2.1. Set exit status

When the run method is executed, the thread will exit. But sometimes the run method will never end, such as using threads in the server program to listen to client requests, or other tasks that need cyclic processing. In this case, these tasks are generally placed in a loop, such as a while loop. If you want to make the while loop exit under a specific condition, the most direct way is to set a boolean flag and control whether the while loop exits by setting this flag to true or false.

public class Test1 {

    public static volatile boolean exit =false;  //Exit flag
    
    public static void main(String[] args) {
        new Thread() {
            public void run() {
                System.out.println("The thread started");
                while (!exit) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("The thread is over");
            }
        }.start();
        
        try {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        exit = true;//Change the value of the exit flag after 5 seconds. Without this code, the thread can't stop all the time
    }
}

1.2.2. Use interrupt method

Thread.interrupt() method: used to interrupt the thread. The interrupt status bit of the thread will be set, that is, set to true. Whether the thread dies as a result of the interrupt, waits for a new task, or continues to run to the next step depends on the program itself. The thread will detect this interrupt flag bit from time to time to determine whether the thread should be interrupted (whether the interrupt flag value is true). It does not interrupt a running thread like the stop method

The interrupt() method only changes the interrupt state and does not interrupt a running thread

The interrupt() method only changes the interrupt state and does not interrupt a running thread

The interrupt() method only changes the interrupt state and does not interrupt a running thread

(say important things three times).

The user needs to monitor the status of the thread and handle it. The method that supports thread interrupt (that is, the method that throws interruptedException after thread interrupt) is to monitor the interrupt state of the thread. Once the interrupt state of the thread is set to "interrupt state", an interrupt exception will be thrown. What this method actually completes is to send an interrupt signal to the blocked thread, so that the blocked thread can exit the blocked state after checking the interrupt ID.

More specifically, if the thread is object wait, Thread. Join and thread Sleep is blocked by one of the three methods. When the interrupt() method of the thread is called, the thread will throw an InterruptedException interrupt exception (the thread must prepare to handle this exception in advance), so as to terminate the blocked state early. If the thread is not blocked, the call to interrupt() will not work until the execution of wait(),sleep(),join(), and then the InterruptedException will be thrown immediately.

Demo:

public static void main(String[] args) {
        Thread thread = new Thread() {
            public void run() {
                System.out.println("The thread started");
                try {
                    Thread.sleep(1000 * 100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("The thread is over");
            }
        };
        thread.start();

        try {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //The function is to throw an interrupt signal when the thread is blocked, so that the thread can exit the blocked state
        thread.interrupt();
    }

When the thread is in sleep, join and wait states, if the thread is marked with an interrupt flag, the thread will throw the same.

See the corresponding output information:

The thread started
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.guang.thread.interupt.Test2$1.run(Test2.java:14)
The thread is over

1.2.3. Interrupt thread with interrupt() + isInterrupted()

this.interrupted(): test whether the current thread has been interrupted (static method).

If the method is called continuously, the second call will return false. Explain in the api document that the interrupted() method has the function of clearing the status. After execution, it has the function of clearing the status ID to false.

(the meaning of this paragraph is that for a new thread, when it is first created, the thread has not been interrupted, so whether the corresponding interrupt status should be false;

If the current thread interrupt state is true, the interrupt state will be cleared to false after calling this method, that is, the thread interrupt state will be erased.)

this.isInterrupted(): test whether the thread has been interrupted, but the status ID cannot be cleared.

Demo:

public class TestInterrupted {
    public static void main(String[] args) {
        System.out.println("Has the current thread been interrupted 1?    "+Thread.currentThread().isInterrupted());
        // true---->false; False does not change
        Thread.interrupted();
        System.out.println("Has the current thread been interrupted 2?    "+Thread.currentThread().isInterrupted());
        // Set interrupt flag
        Thread.currentThread().interrupt();
        System.out.println("Has the current thread been interrupted 3?    "+Thread.currentThread().isInterrupted());
        // Erase mark
        Thread.interrupted();
        System.out.println("Has the current thread been interrupted 4?    "+Thread.currentThread().isInterrupted());
    }
}

View the corresponding output information:

Has the current thread been interrupted 1?    false
 Has the current thread been interrupted 2?    false
 Has the current thread been interrupted 3?    true
 Has the current thread been interrupted 4?    false

You can see that when the thread interrupt state is set to true, after calling the interrupted() method, the interrupt mark is erased and the interrupt state is false.

Let's take another look at the use case:

public static void main(String[] args) {
        Thread thread = new Thread() {
            public void run() {
                System.out.println("The thread started");
                while (!isInterrupted()) {
                    System.out.println(isInterrupted());//true after interrupt is called
                }
                System.out.println("The thread is over");
            }
        };
        thread.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.interrupt();
        System.out.println("Whether the thread is interrupted:" + thread.isInterrupted());//true
    }

See the console output information:

....
false
false
 The thread is over
 Whether the thread is interrupted: true

1.2.4. The thread cannot be terminated

public class Test {
    public static void main(String[] args) {
        Thread thread = new Thread() {
            public void run() {
                System.out.println("The thread started");
                while (true) {//In this case, even if the thread calls the intentrupt() method and isInterrupted(), the thread will continue to run and cannot stop at all!
                    System.out.println(isInterrupted());//true after interrupt is called
                }
            }
        };
        thread.start();
        thread.interrupt();//Note that this method will not interrupt a running thread. Its function is to throw an interrupt signal when the thread is blocked, so that the thread can exit the blocked state
        while (true) {
            System.out.println("whether isInterrupted: " + thread.isInterrupted());//true
        }
    }
}

This is the case: even if the interrupt status is marked, the thread cannot be stopped (if the sleep, join and wait methods are not encountered)

However, there are no wait, sleep and wait methods set in the above demo, so the thread will run all the time. As a result, the thread cannot be terminated.

1.2.5 supplementary description of isInterrupted

public class TestInterrupted {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(1000*10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread.start();
        thread.interrupt();
        System.out.println("The current thread status is:"+Thread.currentThread().isInterrupted());
        System.out.println("The current thread status is:"+Thread.currentThread().isInterrupted());
    }
}

Output console information:

The current thread status is: false
 The current thread status is: false
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.guang.thread.interupt.TestInterrupted.lambda$main$0(TestInterrupted.java:13)
	at java.lang.Thread.run(Thread.java:748)

The reason why the exception information is output is that the corresponding exception runs out of the new thread, and the interrupt state of the main thread has not changed, so two false are printed.

2. Summary

The logic corresponding to the correct interrupt thread should be:

public class MakeUserOfThread {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            int i = 0;
            while (!Thread.currentThread().isInterrupted()) {
                i++;
                // doSomething.............
                if (i == 5) {
                    // Set it as break flag
                    // You can use wait, sleep, and join method calls
                    // But I think it's more elegant to use break
                    Thread.currentThread().interrupt();
                }
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    // As you can see from here, after the interruption, the state is restored
                    System.out.println("The current thread interrupt flag is:"+Thread.currentThread().isInterrupted());
                   /* Thread.interrupted();
                    System.out.println("The current thread interrupt flag is: "+ Thread.currentThread().isInterrupted());*/
                    // Let it terminate
                    break;
                }
            }
        });
        thread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

This is just an implementation idea, which needs to be implemented with the actual scene.

Keywords: Multithreading

Added by danlindley on Wed, 26 Jan 2022 19:26:43 +0200