还是从一道试题说起
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也不会导致异常
如果想进一步了解的可以参考