Stop the thread

1. How to stop a thread correctly?

Use interrupts to inform, not enforce. This is a specification where threads that respond to interrupts are allowed to interrupt, while threads that don’t respond are beyond our control and cannot be interrupted because the stopped thread knows better when to stop/interrupt than the caller who wants it to stop.

(1) Under what circumstances will threads normally stop ordinary cases?

In the normal case, it is runable, not blocking, and in the program it is always added and cannot finish running for a few seconds.

public class ThreadsAbout {
    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = () -> {
            try {
                int num = 0;
                while (num <= 300) {
                    if(! Thread.currentThread().isInterrupted() && num %100= =0) {
                        System.out.println(num + "It's a multiple of 100.");
                    }
                    num++;
                }
                Thread.sleep(1000);
            } catch(InterruptedException e) { e.printStackTrace(); }}; Thread thread =new Thread(runnable);
        thread.start();
        // If the main thread stops at 500ms, the thread should be in
        //Thread.sleep(1000); Is blocked
        Thread.sleep(500); thread.interrupt(); }}Copy the code

The child thread catches the interrupt.

(3) If the thread blocks after each iteration?

If you have sleep or wait in each iteration, you don’t need to check for interrupts in each iteration.

public class ThreadsAbout {
    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = () -> {
            try {
                int num = 0;
                while (num <= 10000) {
                    // There is no interrupt monitoring
                    if (num % 10= =0) {
                        System.out.println(num + "It's a multiple of 10.");
                    }
                    num++;
                    Thread.sleep(10);
                }
                Thread.sleep(1000);
            } catch(InterruptedException e) { e.printStackTrace(); }}; Thread thread =new Thread(runnable);
        thread.start();
        Thread.sleep(500); thread.interrupt(); }}Copy the code

If (num % 10 == 0) Thread.currentthread ().isinterrupted ()

Try /catch problem in while

/** * Description: If a try/catch is put in the while, the interrupt fails */
public class CantInterrupt {

    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = () -> {
            int num = 0;
            // Why does the interrupt detection still work?! No interruption!!
            while (num <= 10000 && !Thread.currentThread().isInterrupted()) {
                if (num % 100= =0) {
                    System.out.println(num + "It's a multiple of 100.");
                }
                num++;
                try {
                    Thread.sleep(10);
                } catch(InterruptedException e) { e.printStackTrace(); }}}; Thread thread =new Thread(runnable);
        thread.start();
        Thread.sleep(5000); thread.interrupt(); }}Copy the code

The result is this

Sleep is designed to clear the interrupt flag after catching an interrupt, so it does not detect a thread interrupt later.

2. Two practices in development

  • Preferred: delivery interrupt

The method of the downstream service directly throws an exception for the upstream service to handle. Note that run() cannot continue to throw exceptions up because it is a rewrite of the Run interface, which does not throw exceptions itself.

/** * Description: Best practice: Priority after catching InterruptedExcetion: Throw an exception in the method signature and run() will force a try/catch */
public class RightWayStopThreadInProd implements Runnable {

    @Override
    public void run(a) {
        while (true && !Thread.currentThread().isInterrupted()) {
            System.out.println("go");
            try {
                throwInMethod();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                // Save the log and stop the program
                System.out.println("Save log"); e.printStackTrace(); }}}private void throwInMethod(a) throws InterruptedException {
            Thread.sleep(2000);
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new RightWayStopThreadInProd());
        thread.start();
        Thread.sleep(1000); thread.interrupt(); }}Copy the code
  • Unwilling or unable to deliver: Resuming the interrupt
/** * Description: Best Practice 2: Call thread.currentThread ().interrupt() in the catch substatement to restore the interrupt state so that subsequent execution can still detect the interrupt that just occurred * return to RightWayStopThreadInProd to restore the interrupt Make it pop out */
public class RightWayStopThreadInProd2 implements Runnable {

    @Override
    public void run(a) {
        while (true) {
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("Interrupted, the program ends.");
                break; } reInterrupt(); }}private void reInterrupt(a) {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        // This line is critical, equivalent to a transfer interruptThread.currentThread().interrupt(); e.printStackTrace(); }}public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new RightWayStopThreadInProd2());
        thread.start();
        Thread.sleep(1000); thread.interrupt(); }}Copy the code
  • Interrupts should not be masked

3. Wrong stop method

  • Deprecated stop,suspend,resume method

But the stop method does turn off the monitor lock. What is the monitor

  • Set the Boolean flag bit with volatile

4. Stop thread-related methods

  • Static Boolean interrupted() Clears the interrupt flag

  • Boolean isinterrupted() checks for interruption. This method does not clear the interrupt flag

  • The target of Thread.interrupted() is the current Thread, regardless of which object the method used comes from.

// Start the thread
        threadOne.start();
        // Set the interrupt flag
        threadOne.interrupt();
        // Get the interrupt flag
        System.out.println("isInterrupted: " + threadOne.isInterrupted());
        // Get the interrupt flag and reset it
        System.out.println("isInterrupted: " + threadOne.interrupted());
        // Get the interrupt flag and straighten it
        System.out.println("isInterrupted: " + Thread.interrupted());
        // Get the interrupt flag
        System.out.println("isInterrupted: " + threadOne.isInterrupted());
Copy the code

The answers are true,false(calling a static method that actually checks whether main’s thread is interrupted),false(ibid.), and true(the first isInterupted() method is an instance method that does not clear the interrupt flag).

Question: How do I stop a thread

  • Principle: Benefits of using interrupts (ensuring data security and giving initiative to the interrupted party)

  • Want to stop the thread, need the requester (interrupt request of a party), is to stop party (response interrupt, need to cooperate with an interrupt request, check the interruption of its response, for example), the child method (threads may call to stop party, the method of interrupt, etc., if there are best throw up, if not pass)

  • Stop /suspend is deprecated, and volatile Boolean does not handle prolonged blocking

Sychronize (u) {// if u is blocked for a long time, u cannot change its blocking state}Copy the code