还是从一道试题说起
public class TestThread {
public static void main(String[] args){
// test1
Thread t1 = new Thread(){
public void run(){
try {
int i = 0;
while(i++<100000000){
}
System.out.println("A1");
} catch (Exception e) {
System.out.println("B1");
}
}
};
t1.start();
t1.interrupt();
// test2
Thread t2 = new Thread(){
public void run(){
try {
Thread.sleep(5000);
System.out.println("A2");
} catch (Exception e) {
System.out.println("B2");
}
}
};
t2.start();
t2.interrupt();
// test3
Thread t3 = new Thread(){
public void run(){
try {
this.wait(50000);
System.out.println("A3");
} catch (Exception e) {
System.out.println("B3");
}
}
};
t3.start();
t3.interrupt();
// test1
Thread t4 = new Thread(){
public void run(){
try {
synchronized (this) {
this.wait(50000);
}
System.out.println("A4");
} catch (Exception e) {
System.out.println("B4");
}
}
};
t4.start();
t4.interrupt();
// test5
try {
t4.start();
System.out.println("A5");
} catch (Exception e) {
System.out.println("B5");
}
}
}
实际运行后,我们发现结果是
B3
B5
B4
B2
A1
为什么会这样呢?其实api文档中就有详细的描述如下:
如果线程在调用 Object
类的 wait()
、wait(long)
或 wait(long, int)
方法,或者该类的 join()
、join(long)
、join(long, int)
、sleep(long)
或 sleep(long, int)
方法过程中受阻,则其中断状态将被清除,它还将收到一个 InterruptedException
。
所以在interrupt执行后,对应的线程会放弃睡眠操作,同时抛出异常。所以这里会输出B2,B3
关于B4,在线程进入this.wait段代码之后,由于wait的特性,会将对象锁释放出来。之后直到interrupt执行之后,会先获取对象锁,之后放弃wait并抛出异常
关于B5,同一thread对象的start方法只能够被调用一次,当已经启动状态下调用start会抛出IllegalThreadStateException
,如果已经结束,有可能对象都被回收了,所以start更不可能
关于A1,涉及到在interrupt执行后到底改变了什么。实际上在线程interrupt后,只是改变了线程的中断状态而已,如果线程不对该状态进行检测,则线程会一直继续执行下去。直到内部任务完成。我们在print A1时同时打印i,会发现,i此时值已经为100000001已经达到退出条件。那么如何让interrupt的线程能够退出呢,方法如下
Thread t1 = new Thread(){
public void run(){
try {
int i = 0;
while(!Thread.currentThread().isInterrupted()){
while(i++<100000000){
}
}
System.out.println("A1 "+i);
} catch (Exception e) {
System.out.println("B1");
}
}
};
t1.start();
t1.interrupt();
结论:
当线程当前在运行状态,如果没有判断isInterrupted标志,实际上什么也不会发生
而当线程在阻塞状态时(sleep wait join),执行interrupt会因为抛出异常而提前退出阻塞状态
当存在同步锁的情况下,wait会将同步锁释放出来,如果拿不到同步锁,interrupt也不会导致异常
如果想进一步了解的可以参考