解析 Thread 中三种跟线程中断有关的方法
时间:2018年10月3日
1. interrupt()
interrupt() 这个方法是将当前线程的中断状态为 true,即调用 isInterrupted() 将返回 true。
其具体实现如下:
public void interrupt() {
    // 只有自己才能够中断自己
    // checkAccess() 这方法会抛出 SecurityException
    if (this != Thread.currentThread())
        checkAccess();
    synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {
            interrupt0(); // Just to set the interrupt flag
            b.interrupt(this);
            return;
        }
    }
    interrupt0();
}
下面来看看例子:
public class InterruptedTheadTest {
	public static void main(String[] args) {
		Thread.currentThread().interrupt();
        System.out.println("the current thread has been interrupted!");
	}
}
结果输出:
the current thread has been interrupted!
结果与单独打印上面这句话一样。为什么不会抛出中断异常呢?
那这个方法到底该怎么用呢?实际上,这个方法是针对于阻塞的线程的。什么意思呢?就是当 处于阻塞的线程 调用 interrupt() 方法,将会抛出 InterruptException 异常。
下面让我们来稍微修改一下上面的代码:
public class InterruptedTheadTest {
	public static void main(String[] args) {
		Thread.currentThread().interrupt();
		try {
			Thread.currentThread().sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
			System.out.println("the current thread has been interrupted!");
		}
	}
}
结果输出:
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.wfms.concurrency.TestInterruptedThead.main(TestInterruptedThead.java:8)
the current thread has been interrupted!
2. isInterrupted()
直接来看源码:
public boolean isInterrupted() {
    return isInterrupted(false);
}
 /**
  * @param CleanInterrupted,true 返回当前线程的中断状态,并清除其中断状态
  * @param CleanInterrupted,false 返回当前线程的中断状态,不清除其中断状态
  */
private native boolean isInterrupted(boolean ClearInterrupted);
isInterrupted() 内部调用了 isInterrupted(false) ,这个方法是测试当前线程的中断状态。
- 
    true,说明当前线程已经被标记被中断状态,再这之后如果调用 wait()、sleep()、join() 这些方法将会抛出 InterruptedException。
- 
    false,说明当前线程未被阻塞。 
3. interrupted()
public static boolean interrupted() {
    return currentThread().isInterrupted(true);
}
前面我们已经介绍过 isInterrupted(boolean) 这个方法,可知 interrupted() 这个方法返回当前线程的中断状态之后,再将其中断状态清除掉。
下面来演示对比 isInterrupted() 和 interrupted() 这两个方法的区别:
public class InterruptedTheadTest {
	public static void main(String[] args) {
		compareIsInterruptedAndInterrupted();
	}
	
	public static void compareIsInterruptedAndInterrupted() {
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				Thread.currentThread().interrupt();
				boolean isInterrupted = Thread.currentThread().isInterrupted();
				System.out.println("t1: before call isInterruped: " + isInterrupted);
				isInterrupted = Thread.currentThread().isInterrupted();
				System.out.println("t1: after call isInterrupted: " + isInterrupted);
			}
			
		});
		
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				Thread.currentThread().interrupt();
				boolean isInterrupted = Thread.currentThread().interrupted();
				System.out.println("t2: before call interrupted: " + isInterrupted);
				isInterrupted = Thread.currentThread().interrupted();
				System.out.println("t2: after call interrupted: " + isInterrupted);
			}
			
		});
		
		t1.start();
		t2.start();
		
	}
}
结果输出:
t1: before call isInterruped: true
t2: before call interrupted: true
t1: after call isInterrupted: true
t2: after call interrupted: false
4. 总结
- interrupt(),将当前线程的中断状态设置为 true。
- isInterrupted(),返回当前线程的中断状态(不清除其中断状态)。
- interrupted(),返回当前线程的中断状态并且清除其中断状态。