理解JAVA线程中断

1. 什么是中断

 线程中断可以理解为线程的一个标识性属性。中断好比其他线程对该线程打了个“招呼“。中断后具体该如何操作取决于线程本身。

线程中断的几个重要方法:

// Thread 类中的实例方法,返回该线程的中断标识位的值
public boolean isInterrupted() {}

// Thread 中的静态方法,检测调用这个方法的线程是否已经中断
// 注意:这个方法返回中断状态的同时,会将此线程的中断状态重置为 false
// 所以,如果我们连续调用两次这个方法的话,第二次的返回值肯定就是 false 了
public static boolean interrupted() {}

// Thread 类中的实例方法,用于设置一个线程的中断状态为 true
public void interrupt() {}

 看一个具体的例子:

package com.dcj.chapter5;

import com.dcj.SleepUtils;

public class InterruptTest {

    public static void main(String[] args) {

        Thread t = Thread.currentThread();

        //中断该线程
        t.interrupt();

        System.out.println(t.isInterrupted());  //true

        //检测调用该方法的线程是否已经中断//会重置中断状态为false
        System.out.println("Thread.interrupted():" + Thread.interrupted());  //true, 但是会将中断状态设置为false

        System.out.println("t.isInterrupted():" + t.isInterrupted());  //false

        System.out.println("Thread.interrupted():" + Thread.interrupted());  //第二次调用,当然是false了

        //中断状态被重置了
        System.out.println("t.isInterrupted():" + t.isInterrupted());

        //中断不影响线程本身执行,仍然可以打印
        System.out.println(t);

        Thread t1 = new Thread(() -> {

            try {
                Thread.sleep(10000);  //sleep方法会响应中断,所以中断后catch块会被执行
            } catch (InterruptedException e) { 
                e.printStackTrace();
            }
        });

        t1.start();

        SleepUtils.second(4);
        t1.interrupt();

    }
}

以下方法在线程被中断时,可以自动的被感知到中断:

  • Object 类的 wait()、wait(long)、wait(long, int)

  • Thread 类的 join()、join(long)、join(long, int)、sleep(long)、sleep(long, int)

当这些状态被感知到时抛出异常时,当前线程的中断状态会被clear掉,也就是变为false.

2. InterruptedException

java中的wait, sleep 等都是阻塞方法,调用该方法后该线程会被阻塞等待唤醒。假如在阻塞等待的过程中,另外一个线程对该线程进行了中断,那么被中断的线程起码能知道这个被中断的信息。具体如何处理这个信息,要么捕获异常,要么继续往上抛出异常,这就有了InterruptedException。当抛出异常时,当前线程的中断状态会被clear掉。

3. 如何优雅的处理InterruptedException

 对于这种抛出InterruptedException的方法,比如 lockInterruptibly.lockInterruptibly() 方法,其实现类是这样的:

#在方法的开头就做判断
public final void acquireInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        //接下来的代码
    }

 可以这么理解,获取锁的方法是一个阻塞方法,因为获取不到锁当前线程会挂起,但是我在刚开始执行的时候,该线程已经被中断了,那么就直接抛出异常给调用者。

你可能感兴趣的:(JAVA)