jdk1.8之线程中断
在Core Java中有这样一句话:"没有任何语言方面的需求要求一个被中断的程序应该终止。中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断 "
线程中断不会使线程立即退出,而是给线程发送一个通知,告知目标线程有人希望你退出。至于目标线程接收到通知后如何处理,则完全由目标线程自行决定。
线程中断有关的三个方法
- void Thread.interrupt();//中断线程
- boolean Thread.isInterrupted()//判断是否中断
- static boolean Thread.interrupted()//判断是否中断,并清除当前中断状态
- Thread.interrupt()方法是一个实例方法,它通知目标线程中断,也就是设置中断标志位。中断标志位表示当前线程已经被中断了。
- Thread.isInterrupted()方法也是实例方法,它判断当前线程是否有被中断(通过检查中断标志位)。
静态方法Thread.interrupted()也是用来判断当前线程的中断状态,但同时会清除当前线程的中断标志位状态。
运行中的线程不会因为interrupt()而中断,因为它仅仅是一个信号(status)
public static void main(String[] intsmaze) throws InterruptedException { Thread t1=new Thread() { public void run() { while(true){ } } }; t1.start(); Thread.sleep(2000); t1.interrupt(); }
这个程序虽然对t1进程了中断,但是在t1中并没有中断处理的逻辑,因此即使t1线程被置上了中断状态,但是这个中断不会发生任何作用。
如果希望t1在中断后退出,必须为他增加相应的中断处理代码,如下
public static void main(String[] intsmaze) throws InterruptedException { Thread t1=new Thread() { public void run() { while(true) { if(Thread.currentThread().isInterrupted())//判断当前线程是否中断。 { System.out.println("intsmaze Interrupt"); break; } } } }; t1.start(); Thread.sleep(2000); t1.interrupt(); }
等待中的线程(wait(long),sleep(long),join(long)收到中断信号会抛出InterruptedException
public static native void sleep(long millis) throws InterruptedException;会抛出一个中断异常。当线程在休眠sleep时,如果被中断就会产生该异常,此时它会清楚中断标志,如果不加处理,那么在下一次循环开始时,就无法捕获这个中断。
如果注释掉catch中的Thread.currentThread().interrupt();我们可以发现,程序一直运行,线程没有停止;反之放开该注释,则发现程序运行结束了。
public static void main(String[] intsmaze) throws InterruptedException { Thread t1=new Thread() { public void run() { while(true) { if(Thread.currentThread().isInterrupted()) { System.out.println("intsmaze Interrupt"); break; } try { Thread.sleep(6000); } catch (InterruptedException e) { System.out.println("Interrupt when intsmaze sleep"); Thread.currentThread().interrupt();//设置中断状态 } } } }; t1.start(); Thread.sleep(2000); t1.interrupt(); }
BLOCKED
如果线程在等待锁,对线程对象调用interrupt()只是会设置线程的中断标志位,线程依然会处于BLOCKED状态,也就是说,interrupt()并不能使一个在等待锁的线程真正”中断”。通过前面的代码可以看到,中断是通过循环不判进行Thread.currentThread().isInterrupted()判断的。
在使用synchronized关键字获取锁的过程中不响应中断请求,这是synchronized的局限性。如果想在等待获取锁的过程中能响应中断,应该使用显式锁,Lock接口,它支持以响应中断的方式获取锁。
NEW/TERMINATE
如果线程尚未启动(NEW),或者已经结束(TERMINATED),则调用interrupt()对它没有任何效果,中断标志位也不会被设置。比如说,以下代码的输出都是false。
IO操作
如果线程在等待IO操作,尤其是网络IO,则会有一些特殊的处理。
如果IO通道是可中断的,即实现了InterruptibleChannel接口,则线程的中断标志位会被设置,同时,线程会收到异常ClosedByInterruptException。
如果线程阻塞于Selector调用,则线程的中断标志位会被设置,同时,阻塞的调用会立即返回。
我们重点介绍另一种情况,InputStream的read调用,该操作是不可中断的,如果流中没有数据,read会阻塞 (但线程状态依然是RUNNABLE),且不响应interrupt(),与synchronized类似,调用interrupt()只会设置线程的中断标志,而不会真正”中断”它,我们看段代码。
public class InterruptReadDemo { private static class A extends Thread { @Override public void run() { while(!Thread.currentThread().isInterrupted()){ try { System.out.println(System.in.read()); } catch (IOException e) { e.printStackTrace(); } } System.out.println("exit"); } } public static void main(String[] args) throws InterruptedException { A t = new A(); t.start(); Thread.sleep(100); t.interrupt(); } }
线程t启动后调用System.in.read()从标准输入读入一个字符,不要输入任何字符,我们会看到,调用interrupt()不会中断read(),线程会一直运行。
拿两年前的笔记出来冒个泡
- 关于java线程中断的几点发现sleep()、wait()等JDK内置的方法抛中断异常后会清掉线程的中断状态
- 从JDK源码角度看java并发线程的中断
- 从JDK源码角度看java并发线程的中断
- JDK1.8 StampedLock: 解决ReentrantReadWriteLock在读多写少情况下,写线程饥饿问题
- CentOS 7中安装Oracle JDK1.8环境
- 基于JDK1.8的ConcurrentHashMap分析
- 安装MAVEN(JDK1.8和Maven3.5)
- ubuntu16.04下配置JDK 1.8+安装Java EE,并实现最大子数组算法
- Ubuntu安装JDK1.8
- Java并发之线程中断
- 【JUC】JDK1.8源码分析之Semaphore(六)
- JDK1.8的String笔记
- Jdk1.8中ConcurentHashMap实现策略的变化
- Win10配置jdk1.8
- java 多线程5: java 终止线程及中断机制 (stop()、interrupt() 、interrupted()、isInterrupted())
- CopyOnWriteArrayList源码分析(基于JDK1.8)
- Java挑战高并发(2):线程中断
- LINUX下使用elasticsearch-jdbc工具实现MySQL同步到ElasticSearch 以及linux 64位centos系统安装jdk1.8
- CentOS安装jdk1.8 及服务器之间的拷贝