JUC programming - thread interruption mechanism and source code analysis

1 What is the interrupt mechanism

  • A thread should not be interrupted or stopped by other threads, but should be stopped by the thread itself - fate is in its own hands;
  • So the Thread.stop, Thread.suspend, and Thread.resume methods are all obsolete;
  • A thread cannot be stopped immediately in Java;
  • Java provides a negotiation mechanism for stopping threads - interrupt, that is, the interrupt identification negotiation mechanism ;
  • The interrupt process needs to be implemented by the programmer - use the thread's interrupt method to set the interrupt flag of the object to true - just a warm reminder, not a forced termination;


2 Description of the three major methods of API methods related to interruption

  • void interrupt():
    • interrupt this thread;
    • Just set the interrupt flag bit and initiate a negotiation;
  • static boolean interrupted():
    • Test whether the current thread has been interrupted;
    • static method;
    • method does two things:
      • Return the interrupt status (true/false) of the current thread to test whether the current thread has been interrupted;
      • Clear the interrupt status of the current thread and reset it to false to clear the interrupt status of the thread ;
  • boolean isInterrupted():
    • Determine whether the current thread is interrupted (by checking the interrupt flag);
    • Used in conjunction with the first method;


3 How to stop interrupting a running thread - code example

3.1 Realized by the keyword volatile variable

import java.util.concurrent.TimeUnit;


public class InterruptDemo
{
    
    
private static volatile boolean isStop = false;

public static void main(String[] args)
{
    
    
    new Thread(() -> {
    
    
        while(true)
        {
    
    
            // 需要退出了 or 需要中断了
            if(isStop)
            {
    
    
                System.out.println(Thread.currentThread().getName()+"线程------isStop = true,自己退出了");
                break;
            }
            System.out.println("-------hello interrupt");
        }
    },"t1").start();

    //暂停几秒钟线程
    try {
    
     TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) {
    
     e.printStackTrace(); }
    isStop = true;
}


3.2 Realized by AtomicBoolean class

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

public class StopThreadDemo
{
    
    
	// init
    private final static AtomicBoolean atomicBoolean = new AtomicBoolean(true);

    public static void main(String[] args)
    {
    
    
        new Thread(() -> {
    
    
            while(true)){
    
    
                if(atomicBoolean.get()){
    
    
                    System.out.println(
                        Thread.currentThread().getName() + "\t atomicBoolean 被修改为true 线程停止"
                    );
                    break;
                }
            
                System.out.println("t1-----hello");
            }
        }, "t1").start();

        // 小睡一会
        try {
    
     TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) {
    
     e.printStackTrace(); }

        // 另一个线程
        new Thread(() -> {
    
    
            atomicBoolean.set(true);
        },"t2").start();
    }
}


}


3.3 Implementation through the interrupt API method that comes with the Thread class

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

public class InterruptTest {
    
    

    public static void main(String[] args) {
    
    
        Thread t1 = new Thread(() -> {
    
    
            while(true) {
    
    
                // 判断中断
                if(Thread.currentThread().isInterrupted()) {
    
    
                    System.out.println(Thread.currentThread().getName() + "\t 中断");
                    break;
                }

                System.out.println("----t1 interrupt");
            }
        },"t1");
        t1.start();

        try {
    
    
            TimeUnit.MILLISECONDS.sleep(20);
        } catch (InterruptedException e) {
    
    
            throw new RuntimeException(e);
        }

        new Thread(() -> {
    
    
        	// 中断
            t1.interrupt();
        },"t2").start();
    }
}


4 Analysis of the underlying source code of the interrupt method

4.1 interrupt() method - no return value

  • Interrupt method function: interrupt this thread;
  • Just set the interrupt flag from false to true ;
  • does not stop the thread immediately ;
  • If the thread is in a blocked state (such as sleep, wait, join, etc.), and the interrupt method of the current thread object is called in another thread, the thread will immediately exit the blocked state (not immediately exit the thread), and throw a InterruptedException exception. ;
  • Interrupting an inactive thread has no effect;

method:

    public void interrupt() {
    
    
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
    
    
            Interruptible b = blocker;
            if (b != null) {
    
    
            	// 实际调用interrupt0()
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }

Call the underlying native method:

    private native void interrupt0();


4.2 isInterrupted() method

public boolean isInterrupted() {
    
    
        return isInterrupted(false);
    }

The bottom layer still calls the native method:

// Tests if some Thread has been interrupted. 
// The interrupted state is reset or not based on the value of ClearInterrupted that is passed.
    private native boolean isInterrupted(boolean ClearInterrupted);


5 interview questions

5.1 Case 1

The interrupt flag of the current thread is true, should it stop immediately?
——It does not stop immediately and requires the cooperation of the thread itself;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

public class InterruptTest {
    
    
    public static void main(String[] args) throws InterruptedException
    {
    
    
        Thread t1 = new Thread(() -> {
    
    
            for (int i=0;i<300;i++) {
    
    
                System.out.println("-------"+i);
            }
            System.out.println("after t1.interrupt()--第2次---: "+Thread.currentThread().isInterrupted());
        },"t1");
        t1.start();

        // 默认是false
        System.out.println("before t1.interrupt()----: "+t1.isInterrupted());

        //实例方法interrupt()仅仅是设置线程的中断状态位设置为true,不会停止线程
        t1.interrupt();

        //活动状态,t1线程还在执行中 
        try {
    
     TimeUnit.MILLISECONDS.sleep(3); } catch (InterruptedException e) {
    
     e.printStackTrace(); }

        // 这里已经是true 但是程序没有立刻中断
        System.out.println("after t1.interrupt()--第1次---: "+t1.isInterrupted());
        //非活动状态,t1线程不在执行中,已经结束执行了。
        
        try {
    
     TimeUnit.MILLISECONDS.sleep(3000); } catch (InterruptedException e) {
    
     e.printStackTrace(); }
        System.out.println("after t1.interrupt()--第3次---: "+t1.isInterrupted());
    }
}


5.2 Case 2

  • Problem: thread t1 handles the blocking state (sleep), thread t2 calls the interrupt method of t1, and after an exception is thrown, an infinite loop begins, and the program will not end ;
  • Solution: Call Thread.currentThread().interrupt() again in the catch;

Why?

  • 1 Before calling t1.interrupt(), the interrupt flag is false by default;
  • 2 t2 sends an interrupt negotiation, t1.interrupt(), the interrupt flag is set to true;
    • Under normal circumstances, the interrupt flag is true and the program stops;
    • Abnormal situation, t1 is sleeping - the interrupt status of t1 will be cleared (from true to false) , and an InterrptedException will be thrown - resulting in an infinite loop;
  • 3 Set again in the catch block: Thread.currentThread().interrupt(); ——to prevent an infinite loop;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

public class InterruptTest {
    
    
    public static void main(String[] args) {
    
    
        Thread t1 = new Thread(() -> {
    
    
            while(true) {
    
    

                // 中断
                if(Thread.currentThread().isInterrupted()){
    
    
                    System.out.println(Thread.currentThread().getName() + "\t 被设置为true");
                    break;
                }

                // 阻塞 java.lang.InterruptedException: sleep interrupted
                try {
    
    
                    Thread.sleep(200);
                } catch (InterruptedException e) {
    
    
                    // 再调用一次 就不会无限循环了
//                    Thread.currentThread().interrupt();
                    e.printStackTrace();
                }
                System.out.println("----hello");
            }
        }, "t1");

        t1.start();

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

        new Thread(() ->
            t1.interrupt(),"t2").start();


    }
}

5.3 Case 3

——Talk about the understanding of the static method Thread.interrupted()?

Determine whether the thread is interrupted and clear the current interrupt status:
● 1 Return the interrupt status of the current thread, and test whether the current thread has been interrupted;
● 2 Clear the interrupt status of the current thread and reset it to false, then the second call will Return false, the results of two consecutive calls may be different;

public class InterruptTest {
    
    
    public static void main(String[] args) {
    
    

        // main线程 连续两次调用
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());
        System.out.println("-----------1");
        // 设置中断
        Thread.currentThread().interrupt();
        System.out.println("-----------2");
        // 连续两次调用
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());
        //        main false
        //        main false
        //                -----------1
        //                -----------2
        //        main true
        //        main false
    }
}

Two underlying codes:
both bottom layers call the isInterrupted method, one defaults to true, and the other defaults to false;

    public static boolean interrupted() {
    
    
        return currentThread().isInterrupted(true);
    }
    public boolean isInterrupted() {
    
    
        return isInterrupted(false);
    }

Guess you like

Origin blog.csdn.net/COINVK/article/details/130107731