[TOC]
Thread类的interrupt方法倒是见过好几次,但是一直不知道他的具体是干什么的,今天查了以下api和core java大概解决了自己的疑惑。(顺便吐槽一下core java的翻译,问题实在不少)
一、关于interrupt state
There is boolean flag in every thread that indicating the interrupt state,When the interrupt method is called on a thread, the interrupted status of the thread is set. --core java
每个线程都有一个布尔变量表示线程的中断状态,当线程调用interrupt后,线程的中断状态会设置.
另外,中断状态 可以通过线程的isInterrupted()返回值来判定,true表示设置为中断状态,false表示非中断状态;
The interrupt method can be used to request termination of a thread. --core java
interrupt方法可以请求中断一个线程(也就是说只是请求中断,并不能直接中断).
以下代码验证了上述结论,可以看到程序的输出会出现这种情况:首先为false,interrupt以后,变为true,但是程序依旧会输出0到9;
private void simpleInterrupt() {
Thread t = new Thread(){
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
};
t.start();
System.out.println("before interrupt:" + t.isInterrupted());
t.interrupt();
System.out.println("after interrupt:" + t.isInterrupted());
}
由此可见,interrupt并不像它的中文意思中断一样能中断线程,但是改变了isInterrupted方法的返回值,这个还是可以作为run方法的循环结束的条件,从而中断线程,代码如下:
private void simpleInterruptAffect() {
Thread t = new Thread(){
@Override
public void run() {
for (int i = 0; i < 100 && !isInterrupted(); i++) {
System.out.println(i);
}
}
};
t.start();
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.interrupt();
}
多运行几遍,发现i没到99就结束了。
二、sleep、wait等方法和interrupt的联系
1. If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException. --doc
当线程由于sleep或者wait等方法阻塞时,如果调用了interrupt方法,就会抛出一个异常(补充:core java上说是由于系统无法检测处于阻塞状态线程的interrupt state),并且清除掉线程的interrupt status(使得isInterrupted方法返回false),用代码验证一下:
private void interruptSleep() {
Thread t1 = new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("interrupt status in catch:" + isInterrupted());
}
}
};
t1.start();
System.out.println("interrupt status before interrupt:" + t1.isInterrupted());
t1.interrupt();
System.out.println("interrupt status after interrupt:" + t1.isInterrupted());
}
一般会依次输出
interrupt status before interrupt:false
interrupt status after interrupt:true
interrupt status in catch:false
2. 线程不能睡眠的原因
If you call the sleep method when the interrupted status is set, it doesn’t sleep. Instead, it
clears the status and throws an InterruptedException.
如果线程睡眠前线程它的isInterrupted返回true,线程就不会睡眠,相反,线程的会清除掉interrupt status并且抛出一个异常。同样用代码验证一下。
volatile boolean flag = false;
private void interruptThenSleep() {
Thread t = new Thread(){
@Override
public void run() {
while(!flag){}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("interrupt status in catch:" + isInterrupted());
}
}
};
t.start();
t.interrupt();
System.out.println("interrupt status after interrupt:" + t.isInterrupted());
flag = true;
}
t线程不会休眠10s
并且输出:
interrupt status after interrupt:true
interrupt status in catch:false
到这里可也以得出结论:只要线程的isInterrupted()返回true,Thread.sleep()都会抛出异常,并且清除线程的中断状态。
3.关于interrupted
Tests whether the current thread has been interrupted. The interrupted status of the thread is cleared by this method. --doc
检测当前线程是否处于中断状态,调用后中断状态会重置(状态变量变为false)
同样验证一下
package com.basic;
/**
* Created by liouville on 3/25/16.
*/
public class CompareInterrupt {
volatile static boolean flag = true;
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
System.out.println("主线程:" + t.isInterrupted());
t.interrupt();
flag = false;
}
private static class MyThread extends Thread{
@Override
public void run() {
super.run();
System.out.println("run...");
while (flag){yield();}
System.out.println(isInterrupted());
System.out.println(interrupted());
System.out.println(isInterrupted());
}
}
}
一般输出:
主线程:false
run...
true
true
false
三、interrupt interrupted isInterrupted
现在可以更清晰的看到三者之间的区别。
interrupt用来请求中断线程,但是只是设置一下线程的中断状态的标记变量,并不会直接中断线程。
isInterrupted用来判断调用该方法的线程是否处于中断状态,处于中断状态返回true,否则false;,不会影响这个中断状态标记变量的值。
interrupted是一个静态方法,也是用来检测当前线程是否处于中断状态,处于中断状态返回true,否则false,但是它会重置中断状态的标记变量为false.**