JUC Multithreading: Interrupt stop of thread

        For the stop of the thread, usually we do not stop it manually, but wait for the thread to run to the end naturally, but in actual development, in many cases, we need to manually stop the thread in advance, such as an exception in the program error, the user closes the program, etc. If you can't stop the thread well, it may cause various problems, so it is very important to stop the thread correctly. The common ways to interrupt the thread are as follows:

1. Method 1: Use the stop() method of the Thread class to terminate the thread:

        Although the stop() method of the Thread class can terminate the thread, this method has been marked as an abandoned method. The reason is that the stop() method is too violent. Even if the thread is only half executed, it will be forcibly terminated, and the correct release of thread resources cannot be guaranteed. , which is thread-unsafe and produces unpredictable results, so it is not recommended to use it.

2. Method 2: Determine whether the thread needs to be interrupted according to the flag modified by volatile:

    public static class ChangeObjectThread extends Thread 
    {
		// 表示是否停止线程
		private volatile boolean stopMe = true;
		public void stopMe() {
			stopMe = false;
		}
 
		@Override
		public void run() {
			while (!stopMe) {
                System.out.println("I'm running");
			}
		}
	}

        In the above code, a marker variable stopMe is defined to identify whether the thread needs to exit. When the stopMe() method is called, stopMe will be assigned to false. At this time, the while(!stopMe) in the code is The change will be detected and the thread will exit

3. Method 3: Terminate the thread through the interrupt interrupt mechanism:

        The core of this method is to set the interrupt flag bit of the thread through the interrupt() method, and monitor and judge the interrupt signal through the isInterrupt()/interrupted() method. When the thread detects that it is true, it means that the interrupt signal is received. The interrupted thread does the corresponding processing. But how to respond to the interrupt signal, the interrupted thread has complete autonomy, that is, the interrupt result is death or continues to run, depending on the logic of the interrupted thread itself.

  • Thread.interrupte(): Set the thread's interrupt flag to true, indicating that it was interrupted by other threads, but it will not force the interruption of the running thread like the stop() method, but only serves to notify the stopped thread. ; And the interrupted thread needs to respond by monitoring whether its own flag is interrupted, such as using the isInterrupted() or interrupted() method to determine whether it is interrupted;
  • this.interrupted(): Tests whether the current thread has been interrupted. If this method is called twice in a row, the first time returns true, the second time returns false, because the interrupted() method has the function of clearing the state, its internal implementation is the isInterrupted() of the current thread that is called, and the current thread is reset interrupt status.
  • this.isInterrupted(): Tests whether the thread has been interrupted, but does not clear the status flag

        As mentioned earlier, the interrupt mechanism needs to be interrupted by the thread to monitor whether the interrupt flag has changed and dealt with it, then when the thread is in a blocked state, to be precise, the thread is blocked by Object.wait(), Thread.join() and Thread.sleep () What should I do when one of the three methods blocks? In fact, the interrupt() method also supports thread blocking. Once the interrupt status of the thread is set to "interrupted" in the above cases, the interrupt exception InterruptedException will be thrown, thereby terminating the blocked state early, so we only All you need to do is catch the InterruptedException and respond to the interruption. However, before throwing an InterruptedException, the JVM will reset the thread's interrupt flag, so calling the isInterrupted() method at this time will return false, but if the thread is neither blocked nor passed isInterrupted()/isInterrupted() Monitor and act accordingly, calling interrupt() will have no effect at this time. Below we write two examples for the two interrupt() mechanisms:

3.1. Use interrupt() + isInterrupted() to interrupt the thread:

 public static void main(String[] args)
    {
        //创建 interrupt-1 线程
        Thread thread = new Thread(() -> {
            while (true) {
                System.out.println(Thread.currentThread().getName() + "线程正在执行...");
                if (Thread.currentThread().isInterrupted())
                {
                    System.out.println("线程1 接收到中断信息,中断线程...中断标记:" + Thread.currentThread().isInterrupted());
                    Thread.currentThread().interrupted(); 
                    System.out.println("经过 Thread.interrupted() 复位后,中断标记:" + Thread.currentThread().isInterrupted());
                    break;
                }
            }
        }, "interrupt-1");
        //启动线程 1
        thread.start();

        //创建 interrupt-2 线程,用于设置线程1的中断状态
        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("设置线程中断...." );
            thread.interrupt();

        },"interrupt-2").start();
    }

3.2. Use interrupt() + InterruptedException to interrupt the thread:

    public static void main(String[] args)
    {
        //创建 interrupt-1 线程
        Thread thread = new Thread(() -> {
            while (true) {
                System.out.println(Thread.currentThread().getName() + "线程1开始执行...");
                //判断当前线程是否中断,
                if (Thread.currentThread().isInterrupted())
                {
                    System.out.println("线程1 接收到中断信息,中断线程...中断标记:" + Thread.currentThread().isInterrupted());
                    break;
                }

                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    //因为抛出InterruptedException异常后,会导致中断标志复位为false,所以再次设置线程的中断状态,也可以直接使用break中断线程
                    Thread.currentThread().interrupt();
                    //break;
                }
            }
            System.out.println("线程1执行结果...");
        }, "interrupt-1");
        //启动线程 1
        thread.start();

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("设置线程中断...." );
        //用于设置线程1的中断状态
        thread.interrupt();
    }

        It can be proved from the above execution results that when the thread is in a blocked state, it can also feel the interruption notification and throw an exception, so there is no need to worry that the thread will not feel the interruption during a long sleep.

        The most correct and elegant way to stop a thread is to use interrupt(), but interrupt() only serves to notify the stopped thread. For the stopped thread, it has complete autonomy. You can stop immediately, choose to stop after a period of time, or choose not to stop. For example, after throwing InterruptedException, interrupt the setting again, so that the program can continue to terminate the operation; for example, when the thread is performing IO operations, such as writing a file, when it receives a signal to terminate the thread, it will not stop immediately, but Whether to stop or not to stop after writing the entire file successfully depends on the processing of the notified thread, because if the thread is terminated immediately, it may cause data incompleteness, which is not a business undesired result. Then many readers may wonder, what is the meaning of existence in this case, in fact, because for Java, it is expected that programs are management threads that can notify and cooperate with each other

Reference article:

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

https://www.cnblogs.com/i-code/p/13804624.html

Guess you like

Origin blog.csdn.net/a745233700/article/details/122641839