中断机制
java没有提供一种安全的直接的方法来停止某个线程,而是提供了中断机制。中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程,而需要被中断的线程自己吃力。每一个线程对象里有一个标识位标识是否有中断请求,代表着是否有中断请求。
三个中断相关方法
1.interrupt
1 public void interrupt() { 2 if (this != Thread.currentThread()) 3 checkAccess(); 4 5 synchronized (blockerLock) { 6 Interruptible b = blocker; 7 if (b != null) { 8 interrupt0(); // Just to set the interrupt flag 9 b.interrupt(this); 10 return; 11 } 12 } 13 interrupt0(); 14 }
private native void interrupt0();
第8行注释说的很清楚,仅仅是设置中断标识位,这是一个native方法。
2.isInterrupted 这是个实例方法
方法是测试线程是否中断,中断标识位的状态并不受到该方法的信息。也是一个native方法。
3.interrupted 这是个静态方法
方法是测试当前线程是否中断,线程中断标识位会清除。也是native方法。
作为一种协作机制,不会强求被标记中断的线程一定要在某个点进行中断处理,实际上,被中断的线程只需要在合适的时候处理,如果没有合适的时间,也可以不处理。频繁的检查中断可能会导致程序执行效率的低下,较少的检查会导致中断请求得不得及时响应。实际场景中,
如果性能指标比较关键,可能需要建立一个测试模型来分析最佳的中断检测点,以平衡性能和响应灵敏性。
线程中断举例
1 public static void main(String[] args) throws Exception { 2 Runnable runnable = new Runnable() { 3 public void run() { 4 while (true) { 5 if (Thread.currentThread().isInterrupted()) { 6 System.out.println("线程被中断了"); 7 return; 8 } else { 9 System.out.println("线程没有被中断"); 10 } 11 } 12 } 13 }; 14 Thread t = new Thread(runnable); 15 t.start(); 16 Thread.sleep(3000); 17 t.interrupt(); 18 System.out.println("线程中断了,程序到这里了"); 19 }
结果
... 线程没有被中断 线程没有被中断 线程没有被中断 线程没有被中断 线程没有被中断 线程中断了,程序到这里了 线程被中断了
代码分为以下几步:
1、main函数起一个t线程
2、main函数3秒钟之后给t线程打一个中断标识位,表示t线程要中断
3、t线程无限轮询自己的中断标识位,中断了则打印、退出,否则一直运行
从控制台上打印的语句看到,3秒钟中断后,打印出该打印的语句后,就停止了。那这种场景就是前面说的"频繁地检查",导致程序效率低下;那如果不频繁地检查呢,比如在while中的else分支中加上Thread.sleep(500),表示500ms即0.5s检查一次,那这种场景就是前面说的"中断得不到及时的响应"。
其实这个例子中,t线程完全可以不用去管这个中断标识位的,不去检查就好了,只管做自己的事情,这说明中断标识位设不设置是别人的事情,处不处理是我自己的事情,没有强制要求必须处理中断。
但是,那些会抛出InterruptedException的方法要除外。像sleep、wait、notify、join,这些方法遇到中断必须有对应的措施,可以直接在catch块中处理,也可以抛给上一层。这些方法之所以会抛出InterruptedException就是由于Java虚拟机在实现这些方法的时候,本身就有某种机制在判断中断标识位,如果中断了,就抛出一个InterruptedException。